0.8.0 release gate (2026-10-29)
What was run on main a362044 (the PR #139 merge, sixty-three commits
after the 0.7.0 release point e9b2ce8) on Linux x86-64 with QGIS 4.2.3
(Qt 6.11.2), CPython 3.14.8 in the locked Pixi environment, CPython
3.11.2 for the purity lane and the clean installs, Bun 1.4.2. Every line
is a command that ran on this checkout at that commit; nothing is
inferred from CI. The tree is unstamped: the manifests still say
0.7.0 / 0.5.0 / 0.1.0, so the artifact names below carry 0.7.0.
Stamping, tagging and publishing wait for an explicit “Release 0.8.0”.
- Required work (AC 1). TASK-32, 73, 74, 75, 77, 79 and 140 are Done; TASK-73 (console session) and TASK-77 (externals probe and vendoring) were re-scoped in from m-6 and their evidence is below. TASK-76 - the third task AC 1 names - was withdrawn with decision-49 (doc-4): the agent user mode went with it, so external clients reach a plugin through TASK-74’s HTTP API and the MCP list a user’s install offers names only declared actions and streams.
- Scope.
release.py planreadsv0.8.0forallandpythonandts-v0.6.0fortypescript;uiis skipped (no release-worthy commit sinceui-v0.1.0). The minor is a decision, not a planner result: sixty-three commits, among them three breaking ones (c278dec,9397dee,114c5fd), the plugin HTTP API and MCP serve, the console session, the externals probe and the firstmcpextra. - The
mcpextra (AC 2). Added in6db189a, after the 0.7.0 release point, so 0.8.0 is the first release wherepip install "qgis-sdk[mcp]"resolves: PyPI’s 0.7.0 kit wheel carries onlycontrolled-deploymentanddev, and its tools wheel no extra at all. The range this train records ismcp==2.3.0- the tools wheel declaresProvides-Extra: mcpwithRequires-Dist: mcp==2.3.0, the kit declaresProvides-Extra: mcpwithRequires-Dist: qgis-sdk-tools[mcp]==0.7.0, and the kit’sdevextra pins the samemcp==2.3.0. The extra’s pin is inside the kit scopeverify-versionsreads (read_kit_pinsreturns runtime, tools and tools[mcp], all 0.7.0), and a dry run ofstamp_kit_pinswith 0.8.0 rewrites it toqgis-sdk-tools[mcp]==0.8.0;stamp_tools_runtime_rangegivesqgis-sdk-runtime>=0.8.0,<0.9. - Python suite with the extra (AC 1). The locked Pixi environment
does not carry
mcp(no dependency of the workspace); installing the extra’s pinnedmcp 2.3.0into it with the environment’s ownpipchanges the run from 2170 passed / 59 skipped / 7 deselected to 2173 passed, 56 skipped, 7 deselected in 138 s - the three tests that skip without the extra run:test_mcp_cli.py6 passed, including the real stdio client (test_stdio_server_exposes_and_runs_cli_commands, a spawnedqgis-sdk mcpoverStdioServerParameters) and the read-only derivationtest_act_is_developer_only_in_the_tool_list(tool_names(developer=False)drops onlyui_act).test_package_extras_are_optional_and_the_kit_forwards_to_toolscovers the extra’s shape. The smoke lane (-m smoke, excluded from the suite above byaddopts) is 7 passed, 4 skipped, 2225 deselected. - One MCP mode, not two.
serve()has a single mode: it serves the developer vocabulary over stdio, and the read-only inventory is derived from it (tool_names(developer=False)) rather than served by a second entry point. AC 1’s “both modes” is therefore evidenced as the served list plus the derivation, and doc-12 documents it that way; no--read-onlyflag was added. - Purity lane. CPython 3.11.2 with
mcp 2.3.0,pytest -m pureinpackages/qgis-sdk-python/tests: 1995 passed, 22 skipped, 68 deselected. The lane is sensitive to the pin: pytest 9.2.0 with hypothesis 6.170.13 fails 38 tests, while the manifest’s9.1.1/6.169.4is green - a dependency-drift finding, not a code finding. - Static gate.
lint-pythonclean,format-python-check406 files,lint-github-actionsclean (actionlint, every workflow),lint-repository9/9 Alint rules (generated files fresh, README mirrors, pins),biome-check192 files,typecheck(bridge and components) exit 0,test-release-tool286 passed plus its four Alint rules, andbridge generate --checkreportsweb/src/bridge.schema.ts is up to dateboth for the reference plugin’s page (simple.plugin:app) and for the host catalogue inexamples/simple. - Suites. Root
bun run test --force10/10 tasks with no cache: config 6, docs 42, bridge 266 (16 files), bridge alias 12, components 100 (14 files,--conditions=browser), ui alias 13, simple-web 6, Python 2173 passed / 56 skipped inside turbo.bun run coverage6/6 tasks: the Python side 95.70 % (20781 statements, 893 missed) against the 90 % gate, with the 0.8.0 suite inside it. The MCP server itself lives in the spawned client’s process, so its measured share (qgis_sdk_tools/mcp.py, 35 %) is the part the client never enters. - Harnesses, one file per process.
QGIS_SDK_SCAFFOLD_WEB=1test_scaffold_web_native.py8 passed (vanilla, React, Vue and Svelte pages generated, installed, tested, built and driven in a realQWebEngineView);QGIS_SDK_REFERENCE=1test_reference_example_native.py5 passed;QGIS_SDK_DEVTOOLS=1test_devtools_native.py9 passed (the dev server’s HMR marker and its bridge, after TASK-77 retargeted the module at the application API);QGIS_SDK_BUILD_INSTALL=1test_bundle_native.py1 passed - two built ZIPs unpacked into a fresh profile’spython/pluginsthe way Install from ZIP does and started inside QGIS Desktop offscreen with everyqgis_sdkimport refused, so each runs from its own vendored tree;test_desktop_host_native.py4 passed;test-reference-example20 pure + 7 QGIS. - Artifacts (AC 4).
release-build-pythonbuilt three wheels andtwine checkpassed on all of them (unstamped names):qgis_sdk-0.7.0,qgis_sdk_runtime-0.7.0(noRequires-Distat all, so the runtime still declares no dependencies) andqgis_sdk_tools-0.7.0(qgis-sdk-runtime>=0.7.0,<0.8,typer==0.27.3). - Clean install (AC 3). A fresh CPython 3.11.2
venvwith the three wheels: 12 distributions,pip checkclean. The samevenvafterpip install "qgis-sdk[mcp]==0.7.0": 40 distributions (addingmcp 2.3.0andmcp-types 2.3.0and their tree),pip checkclean, andqgis-sdk mcp --helprenders “Serve SDK command tools over MCP stdio (requires the mcp extra)”. Without the extra the command is absent and the documented refusal test covers the message. One installation trap worth recording:pip install "qgis-sdk[mcp] @ file://...kit...whl" --find-links dist/pypi/toolsstill resolvedqgis-sdk-tools==0.7.0from the index, which has no extra, so pip warned and the extra did nothing - install the local tools wheel first. A 0.7.0 user sees the same warning until 0.8.0 ships. - Scaffold. From the installed 0.7.0 wheels,
qgis-sdk new fresh_plugin --ui native --web vanillawritesqgis-sdk-runtime>=0.7,<0.8,qgis-sdk-tools>=0.7,<0.8and"@archont561/qgis-sdk": "0.5.0", andcheckis clean on its four files. - Compatibility and the TypeScript delta (AC 5). The expected zero
bridge delta is false as written: 27 files changed in
packages/qgis-sdk-typescriptbetweene9b2ce8and HEAD - the bridge split intosrc/bridge/{client,errors,frames,protocol}.tsandsrc/stores/{base,form,host-query,operation,stream}.ts, two breaking commits (c278decremoves two bridge errors nothing throws,9397deeunifies introspection and retires the Pydantic adapter) and the Pydanticgenerate:contract-typesleg removed. The wire is unchanged:HOST_FINGERPRINTissha256:16790dc8...exactly as at the 0.7.0 tag,HOST_SCHEMA_VERSION = 1andBRIDGE_PROTOCOL_VERSION = 1, so a 0.5.0 page keeps working against an 0.8 host. The train therefore includests-v0.6.0(owner decision): the bridge is versioned and qualified with the Python pair rather than left at an unchanged 0.5.0 while its own sources moved. The ui components’ peer range>=0.5.0 <0.6.0holds the bridge at 0.5.0 today and refuses a stamped 0.6.0, so the stamp pull request moves it to>=0.6.0 <0.7.0(and the scaffold’sSDK_NPM_VERSION) in the same commit. - Verify.
verify-versionsagrees on 0.7.0 for the Python scope (runtime, tools and the kit, which carries three pins: runtime, tools and tools[mcp]), 0.5.0 for the TypeScript scope (up to the stamp), 0.1.0 for the ui manifests, and plugin description contract version 1 across the Python declarations and the TypeScript bridge. - Licences (AC 3). The 40 distributions the extra installs are
MIT, BSD-2-Clause, BSD-3-Clause, Apache-2.0, ISC or PSF-2.0 only - no
copyleft - and the
mcptree itself is MIT (mcp,mcp-types,annotated-types,pydantic,jsonschema,anyio).DEP001still refuses third-party code inside a plugin. - Docs.
docs-buildrenders 80 pages, anddocs-link-checkresolves 8096 internal links on 120 pages with 0 broken (7582 on 117 before this record and the rehearsal plan were added; the run predates both, which is why its own numbers moved). doc-12 carries the 0.8.0 notes for every added name (the application API andmodule:app, the plugin HTTP API and its security model,qgis-sdk mcpand the developer-only vocabulary, processing destinations) plus the console section, and doc-13 holds the next minor’s draft. - TASK-141 (AC 6). Still In Progress with its own AC 4 open: visible GUI, other platforms and Conda packaging stay unqualified. This gate moves that AC forward with what can be measured here - the desktop host harness 4 passed, the ZIP-install harness 1 passed in real QGIS offscreen, the devtools harness 9 passed, and full workspace coverage - but does not close it, and this record does not claim cross-platform or visible-GUI qualification.
- Stamp steps this train must not miss.
stamp --scope python --version 0.8.0moves the kit, runtime and tools manifests, the kit’s three exact pins (the[mcp]extra included), the tools’ runtime range (>=0.8.0,<0.9), the recipe’s three versions and the example’s windows (>=0.8,<0.9);stamp --scope typescript --version 0.6.0movespackage.json, the alias and its pin and the scaffold pinSDK_NPM_VERSION; by hand, the components’ and their alias’s peer range, the two migration-note headings, the READMEs’ and the guides’ status lines and the one test literal the scaffold pins assert. - Stamp rehearsal (AC 2). Both stamps were run on this tree and then
reverted (
git checkout -- ., and the wheels rebuilt at the unstamped names):stamp --scope python --version 0.8.0andstamp --scope typescript --version 0.6.0move eight files - the three pyprojects,recipe.yaml,examples/simple/pyproject.toml, the TypeScriptpackage.json, the alias andscaffold/web.py- and the kit’s pins readqgis-sdk-runtime==0.8.0,qgis-sdk-tools==0.8.0andqgis-sdk-tools[mcp]==0.8.0, the tools’ range>=0.8.0,<0.9, the example’s windows>=0.8,<0.9.verify-versionsthen fails on exactly one thing - the components’ peer range, with its remediation - and agrees on all five scopes once it moves to>=0.6.0 <0.7.0. On the stamped tree the three wheels build and twine-check as0.8.0; a fresh CPython 3.11.2venvscaffoldsqgis-sdk-runtime>=0.8,<0.9,qgis-sdk-tools>=0.8,<0.9and"@archont561/qgis-sdk": "0.6.0"withcheckclean on four files, while a project scaffolded by the published 0.7.0 under those tools reports exactlyVERSION001andVERSION004with their remediations and nothing else. The stamped tree’s purity lane fails six tests, all of them the one literal intest_scaffold_web.py(SDK_NPM_VERSION == "0.5.0") - that line, the peer range and the two migration-note headings are the whole code change the stamp pull request needs. - Not run here.
build:conda(conda-forge is unreachable from the sandbox, as in the 0.7.0 gate: TLS handshake EOF); the Windows and macOS QGIS rows (m-11, TASK-33); a visible-GUI Desktop session. - Stamp and artifacts (2026-10-29, the stamp pull request). On the
gate record’s merge
951ec3f:release.py stamp --scope python --version 0.8.0moved the kit, runtime and tools manifests, the kit’s three exact pins (runtime, tools andtools[mcp], all==0.8.0), the tools’ runtime range (>=0.8.0,<0.9), the recipe’s three versions and the example’s windows (>=0.8,<0.9);stamp --scope typescript --version 0.6.0movedpackage.json, the alias (and its pin) and the scaffold pinSDK_NPM_VERSION. By hand, as the rehearsal predicted: the components’ peer range on@archont561/qgis-sdkto>=0.6.0 <0.7.0in both the scoped package and its alias (the alias’s copy is not a stamp target and only the alias mirror test caught it, which failed the first stampedbun run test --force),test_scaffold_web.py’s one literal (0.5.0→0.6.0), the doc-12 heading to 0.8.0 migration notes and the doc-13 heading to 0.6.0 migration notes (the site now publishespython-migration/v0-8andtypescript-migration/v0-6without the Draft badge), and the status lines of the README and the five package READMEs.verify-versionsagrees on 0.8.0 for the Python scope, 0.6.0 for the TypeScript scope, 0.1.0 for the ui manifests with the peer range holding the bridge, and contract version 1 in both languages. - On the stamped tree. Static gate clean (ruff 406 files, actionlint,
Alint 9/9, Biome 192 files, typecheck exit 0),
test-release-tool286 passed plus its four Alint rules,bridge generate --checkup to date for the reference plugin’s page. Rootbun run test --force10/10: config 6, docs 42, bridge 266, alias 12, components 100, ui alias 13, simple-web 6, Python 2173 passed / 56 skipped (the first run of the stamped tree failed only the alias mirror test, above).bun run coverage6/6 with the Python side at 95.70 %; the CPython 3.11.2 purity lane 1995 passed / 22 skipped. Harnesses, one file per process: scaffold-web 8, reference 5, devtools 9, build-install 1, desktop host 4, reference example 20 pure + 7 QGIS.docs-build80 pages anddocs-link-check8096 links on 120 pages, 0 broken. - Stamped artifacts.
build-python+verify-pythonpass onqgis_sdk-0.8.0-py3-none-any.whl(0b390cf8…, pinsqgis-sdk-runtime==0.8.0andqgis-sdk-tools==0.8.0, extrasdevandmcpwithRequires-Dist: qgis-sdk-tools[mcp]==0.8.0),qgis_sdk_runtime-0.8.0-py3-none-any.whl(f7828256…, 129 modules, noRequires-Distat all, MITLICENSEindist-info/licenses) andqgis_sdk_tools-0.8.0-py3-none-any.whl(b61c3d33…,qgis-sdk-runtime<0.9,>=0.8.0,typer==0.27.3, extramcpwithmcp==2.3.0).bun pm packproducedarchont561-qgis-sdk-0.6.0.tgz(c7604ed5…, 7 entries),qgis-sdk-0.6.0.tgz(8734dc55…), and the two unchanged ui tarballs at 0.1.0 (3d6767ff…,54d74d9f…) whose peer range now reads>=0.6.0 <0.7.0; all four carry theirLICENSE. - A clean 0.8.0 install. Fresh CPython 3.11.2
venvwith only the three wheels: 12 distributions,pip checkclean;qgis-sdk new --ui native --web vanillawritesqgis-sdk-runtime>=0.8,<0.9,qgis-sdk-tools>=0.8,<0.9and"@archont561/qgis-sdk": "0.6.0", andcheckis clean.pip install "qgis-sdk[mcp]==0.8.0"in the same venv resolvesmcp 2.3.0andmcp-types 2.3.0with no “does not provide the extra” warning - the first release where that works -pip checkstays clean andqgis-sdk mcp --helprenders. A project scaffolded by the publishedqgis-sdk==0.7.0under those tools reports exactlyVERSION001andVERSION004with their remediations and nothing else. - Approval. The gate itself records none. The owner’s “release”
instruction covers the stamp pull request and its record here; the two
tags on that pull request’s merge commit -
python-v0.8.0andts-v0.6.0- are cut after the rehearsal described in the next section, andui-v0.1.0is not re-tagged.