Record compatible-release browser and headless acceptance

This commit is contained in:
Forge
2026-09-22 03:14:07 +00:00
parent 79f2d9f1ca
commit 79fd602b5e
5 changed files with 553 additions and 2 deletions
@@ -0,0 +1,414 @@
{
"source_revision": "79f2d9f1cab2e19ad35fb99f4e215da8f9d5fdfa",
"source_tree": "1205687f3c4a60a30565efcc94592d78e50f9ddc",
"source_sha256": {
"CHANGELOG.md": "2f99f5088cb3363d5c157bb82451b2cde37ebf9291cdef5259b97204f0d14dd9",
"__tests__/cli-version.test.ts": "7f2263a10cbee34d67ca44d514abb0c0da13d165b30fe8698fdc2969982aabc3",
"__tests__/extension-releases.test.ts": "3dda48db9b97b4ac9ea437d62d1f503e91f2f8ea5ec8592f2230843cfb2197db",
"docs/extensions/authoring.md": "224c5c8652a469c98857bafeefd69894e69709e302cc58eff50f8d399ba8c88b",
"marketplace/public/app.js": "c7a8681945d82de27c2e46f8c76f08cdd616a54ab7aaae118091be8b7bc2fdea",
"scripts/validation/extensions-compatibility.cjs": "e6b9a6dfdb27f59a9398f88f6df7726bb6e2c850581849aeb536add7878d5194",
"scripts/validation/marketplace-browser.cjs": "76194905d863800ad7d173d54137eb0195038fde2bae9a1eb450d6f2c0be3153",
"src/bin/codegraph.ts": "021b46718a6aa45a4edc01a001bfaa912f3d98dd515a5a704fdf866aa60bc23c",
"src/plugins/bridge.ts": "2a8f7b86e480a58d87e9f081c3292ec22885b597107b2c26b76a6d89fb9e86f8",
"src/plugins/cli.ts": "9af94178b540ea4975d5a7b715730132c69409004f8dcd09f99bd84f936aea00",
"src/plugins/manager.ts": "7c24442476b5fc63f84fe047df3f4e371059e1973bdbc5b35a9e45e6e5d97134",
"src/plugins/marketplace.ts": "605dc8c53abf67d55a0a4b04ef305535ff3dc3456bf7fa2b6cb184ce49cb0e92",
"src/plugins/releases.ts": "96988d116ea6aa0c106c0a9dcfc2031f9da969888e75e9f60cedc3882a8cec97"
},
"checks": [
{
"command": [
"npm",
"run",
"build"
],
"cwd": "/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph",
"started_at": "2026-09-22T03:09:27.479283+00:00",
"revision": "eab93c311434e1a5878c680a52b8c072da5ff772",
"working_tree": " M __tests__/cli-version.test.ts\n M marketplace/public/app.js\n M scripts/validation/extensions-compatibility.cjs\n M src/bin/codegraph.ts\n",
"exit_code": 0,
"seconds": 32.724,
"finished_at": "2026-09-22T03:10:00.203028+00:00",
"summary": [],
"receipt_path": ".qa/recovery/compat-cli-fix-build.json",
"log_path": ".qa/recovery/compat-cli-fix-build.log",
"log_sha256": "3bba6fec83b4be911d5685d45371e7461b42e3c89143f2a21f998d2d6c5d7c3b"
},
{
"command": [
"npx",
"vitest",
"run",
"__tests__/extension-releases.test.ts",
"__tests__/extension-marketplace.test.ts",
"__tests__/extension-author.test.ts",
"__tests__/plugins.test.ts",
"__tests__/extension-explore.test.ts",
"__tests__/npm-sdk.test.ts",
"__tests__/cli-install-init.test.ts",
"__tests__/cli-version.test.ts",
"--maxWorkers=2",
"--minWorkers=1"
],
"cwd": "/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph",
"started_at": "2026-09-22T03:10:54.157173+00:00",
"revision": "79f2d9f1cab2e19ad35fb99f4e215da8f9d5fdfa",
"working_tree": "",
"exit_code": 0,
"seconds": 18.087,
"finished_at": "2026-09-22T03:11:12.244376+00:00",
"summary": [
"Test Files 8 passed (8)",
"Tests 43 passed (43)",
"Duration 16.05s (transform 3.61s, setup 0ms, collect 10.08s, tests 12.62s, environment 3ms, prepare 1.32s)"
],
"receipt_path": ".qa/recovery/compat-focused-final.json",
"log_path": ".qa/recovery/compat-focused-final.log",
"log_sha256": "3441fe1eb195e7a44a6f80476dd035880573d148b92ed7aeee7ab1fb7eace0e8"
},
{
"command": [
"node",
"--test",
"scripts/validation/extensions-runtime.test.cjs"
],
"cwd": "/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph",
"started_at": "2026-09-22T03:11:13.854565+00:00",
"revision": "79f2d9f1cab2e19ad35fb99f4e215da8f9d5fdfa",
"working_tree": "",
"exit_code": 0,
"seconds": 7.52,
"finished_at": "2026-09-22T03:11:21.374094+00:00",
"summary": [],
"receipt_path": ".qa/recovery/compat-workers.json",
"log_path": ".qa/recovery/compat-workers.log",
"log_sha256": "902d611c9e10018ba53ede698aec98d84bfc4d5cdd6f2e911f5b1300d08387d4"
},
{
"command": [
"node",
"scripts/validation/extensions-compatibility.cjs"
],
"cwd": "/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph",
"started_at": "2026-09-22T03:10:06.389817+00:00",
"revision": "79f2d9f1cab2e19ad35fb99f4e215da8f9d5fdfa",
"working_tree": "",
"exit_code": 0,
"seconds": 24.301,
"finished_at": "2026-09-22T03:10:30.691130+00:00",
"summary": [],
"receipt_path": ".qa/recovery/compat-e2e-verified.json",
"log_path": ".qa/recovery/compat-e2e-verified.log",
"log_sha256": "c3097f4ef12522a0248149e234e0ccaf9c6733f9c2df84c60a06ac67c6c24d07"
},
{
"command": [
"node",
"scripts/validation/marketplace-browser.cjs"
],
"cwd": "/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph",
"started_at": "2026-09-22T03:11:38.183791+00:00",
"revision": "79f2d9f1cab2e19ad35fb99f4e215da8f9d5fdfa",
"working_tree": "",
"exit_code": 0,
"seconds": 14.119,
"finished_at": "2026-09-22T03:11:52.303059+00:00",
"summary": [],
"receipt_path": ".qa/recovery/compat-browser-regression.json",
"log_path": ".qa/recovery/compat-browser-regression.log",
"log_sha256": "a75f9b58660eb4607daaf5c0df45fd5fec719f69f893f7c6925f296fc6409ed2"
}
],
"compatibility": {
"checks": [
"signed immutable versions; semantic catalog order independent of publication order",
"one browser Install selects 1.10.0 over incompatible 9.0.0 and preview; actual Python graph refreshed only in chosen destination",
"no-compatible browser selection/command fails usefully and preserves existing config/graph",
"headless automatic selection agrees; exact incompatible pin/no-compatible/missing update fail without mutation",
"prerelease requires explicit exact pin; automatic update refuses downgrade; explicit lower pin remains exact",
"compatible but broken update retains previous version and graph",
"browser and headless update to highest compatible stable; stale graph labels removed",
"exact artifact URL/file semantics preserved",
"removal cleans contributions; desktop/mobile display actual destination compatibility; no page errors"
],
"releases": [
{
"id": "compatible-demo",
"version": "1.10.0",
"engines": ">=1.6.0 <2",
"integrity": "d59f9b1e9bd7d027081de45ab004aefe3236708ddeb4fc7135c92502ce0866d8"
},
{
"id": "compatible-demo",
"version": "1.9.0",
"engines": ">=1.6.0 <2",
"integrity": "07e64445b8c7205ec9a1d76c9e29affbd55d45e0817e9c3d92572b9f00486fcd"
},
{
"id": "compatible-demo",
"version": "0.5.0",
"engines": ">=1.6.0 <2",
"integrity": "ad3c944ff2bea24feb81cb25839746b72e4845b9dae3cba3a4e2ce872855114d"
},
{
"id": "compatible-demo",
"version": "20.0.0-beta.1",
"engines": ">=1.6.0 <2",
"integrity": "1a24723ecad51739315c4a6439227ff0a884700647ac505db74a12949fa99c82"
},
{
"id": "compatible-demo",
"version": "9.0.0",
"engines": ">=9",
"integrity": "c3f802635737b02d15f6fe3e82cde56c41a1c83c8a9cc0858ef964b49be206c9"
},
{
"id": "unavailable-demo",
"version": "1.0.0",
"engines": ">=9",
"integrity": "bc25c179402f994d59e586491cc0921d01ddc6dcf12bea9274982df745f42ef0"
},
{
"id": "compatible-demo",
"version": "2.0.0",
"engines": ">=1.6.0 <2",
"integrity": "5b2f2099fbe51f94a4242f8e81570bacf3a7c16625e8439af3853adab1de65f1"
},
{
"id": "compatible-demo",
"version": "3.0.0",
"engines": ">=1.6.0 <2",
"integrity": "e9f0eecbf6621e6f0ba7fc139d1eb91ffa2899548e0b5e615e3443a0496c8081"
}
],
"commands": [
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"install",
"compatible-demo",
"--registry",
"http://127.0.0.1:43423",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 0,
"seconds": 1.665,
"log_path": ".qa/recovery/compatibility-verified/command-1.log",
"log_sha256": "64f1ac60c8ad25f6569563d24914759b70acf1b73e5cffeef4feb12ce4c226b9"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"install",
"compatible-demo",
"--registry",
"http://127.0.0.1:43423",
"--version",
"9.0.0",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 1,
"seconds": 0.414,
"log_path": ".qa/recovery/compatibility-verified/command-2.log",
"log_sha256": "d93afb7d84337fce0fb443fb79883800bb478b4c94635140b8f67f9734ed2b26"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"update",
"unavailable-demo",
"--registry",
"http://127.0.0.1:43423",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 1,
"seconds": 0.32,
"log_path": ".qa/recovery/compatibility-verified/command-3.log",
"log_sha256": "78fff926f4f8969d8e1705c0a1271cbd63b822579f81d715c2042ad94c80ad45"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"install",
"unavailable-demo",
"--registry",
"http://127.0.0.1:43423",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 1,
"seconds": 0.435,
"log_path": ".qa/recovery/compatibility-verified/command-4.log",
"log_sha256": "83a7b90bfd2c211c6fb4afcf72e261ef7b42bfd6dc21cfb72d530fb970aef44a"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"install",
"compatible-demo",
"--registry",
"http://127.0.0.1:43423",
"--version",
"20.0.0-beta.1",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 0,
"seconds": 1.618,
"log_path": ".qa/recovery/compatibility-verified/command-5.log",
"log_sha256": "5a0ae6eb30e6659515338894feeb98ebeabbcd4f66e01f425110e75e83d7986d"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"update",
"compatible-demo",
"--registry",
"http://127.0.0.1:43423",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 1,
"seconds": 0.423,
"log_path": ".qa/recovery/compatibility-verified/command-6.log",
"log_sha256": "38c1d85e306b15c18732c81df087390b3dfbd3873bc8836e36be492a1fb8a7fa"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"install",
"compatible-demo",
"--registry",
"http://127.0.0.1:43423",
"--version",
"1.9.0",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 0,
"seconds": 1.607,
"log_path": ".qa/recovery/compatibility-verified/command-7.log",
"log_sha256": "74798a107028fa391113eb0b6fa7efac8bfee9c644dbb121892993443666f2f0"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"update",
"compatible-demo",
"--registry",
"http://127.0.0.1:43423",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 0,
"seconds": 1.639,
"log_path": ".qa/recovery/compatibility-verified/command-8.log",
"log_sha256": "be1f77d7dd153abaab34b2a75bdd5c2d036b406fc11da38ee8d4362bd4c26387"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"install",
"http://127.0.0.1:43423/api/download/compatible-demo/1.9.0",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 0,
"seconds": 1.767,
"log_path": ".qa/recovery/compatibility-verified/command-9.log",
"log_sha256": "fec96b4acb520e5ee4d8a42660e9a876f54f08d60c1fc98bcc7b1dcfd2ba6748"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"install",
"/tmp/cg-compatible-NzGUvq/pinned.cgext",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 0,
"seconds": 1.608,
"log_path": ".qa/recovery/compatibility-verified/command-10.log",
"log_sha256": "f03135c33691b92a8cd0834b0ab07175f81eb68d071d2e495c7ef96f6cbb5e69"
},
{
"command": [
"/usr/local/bin/node",
"/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/codegraph/dist/bin/codegraph.js",
"extensions",
"remove",
"compatible-demo",
"--path",
"/tmp/cg-compatible-NzGUvq/headless-python-project"
],
"exit": 0,
"seconds": 1.68,
"log_path": ".qa/recovery/compatibility-verified/command-11.log",
"log_sha256": "303e141e174839575e69f0ae0ddf92ead0470e6dca049ac1edd45fb64b607bde"
}
],
"engineVersion": "1.6.0",
"platform": "linux",
"browser": "153.0.8010.36"
},
"browser_regression": {
"browser": "153.0.8010.36",
"platform": "linux",
"checks": [
"real browser signed publisher upload",
"browser publisher ownership rejection",
"browser invalid-signature failure state",
"browser malformed-package rejection without publication",
"one-click selected-project install verified in SQLite",
"real postMessage wrong-window command ignored",
"failed browser update preserves working version and graph",
"browser update replaces stale graph contributions",
"browser disable/enable/remove verified in SQLite",
"mobile detail fits viewport",
"real postMessage wrong-origin command ignored"
],
"pageErrors": []
},
"screenshots": {
"docs/validation/extensions-compatibility-20260922/mobile-selected.png": "e6d817201490ad00f572d65de913c09be5f77f1e179da7dc9b5f4972a44746b2",
"docs/validation/extensions-compatibility-20260922/desktop-selected.png": "6f1bf3961036fc1800c1aecf5329d5dad335ea0c4936e6ad65b310c2a0663cae"
},
"environment": {
"platform": "Linux x86_64",
"node": "v22.23.2",
"engine": "1.6.0",
"extension_api": 1,
"PLAYWRIGHT_MODULE": "/data/workspace/Chats/109197f0a288be0afa6b7f8902925630f5a0bfde/browser-tools/node_modules/playwright",
"COMPAT_OUTPUT": ".qa/recovery/compatibility-verified",
"BROWSER_OUTPUT": ".qa/recovery/compat-browser-regression"
},
"prior_failed_attempt": {
"receipt": ".qa/recovery/compat-e2e.json",
"log_sha256": "5fdb771ab70b656fe16e1fd381324adb979ec7e2d0c70730ed868d1d32b5f357",
"reason": "Root CLI --version intercepted extension exact-version pin, printing engine version and exiting zero. Fixed by scoped positional parsing in 79f2d9f."
}
}
@@ -0,0 +1,135 @@
# Compatible extension release acceptance — 2026-09-22
Scoped milestone on draft PR [#1911](https://github.com/colbymchenry/codegraph/pull/1911),
branch `feature/extensions-author-kit-20260922`. Source commits
`eab93c311434e1a5878c680a52b8c072da5ff772` and
`79f2d9f1cab2e19ad35fb99f4e215da8f9d5fdfa`. The latter is the clean revision used
by all final runtime/browser/focused checks. Subsequent evidence changes only
documentation. No merge, release, public npm publication or hosted deployment.
## Behavior
`src/plugins/releases.ts` provides one semantic-version selection policy. The
managed installer resolves using its own engine version and supported manifest
API, never a browser-supplied engine claim. Browser `resolve` and registry
install/update commands use that installer. The CLI opts into the same path with
`--registry`; an unqualified file or URL still means an exact artifact.
Automatic selection chooses the highest compatible stable version regardless
of publication order. Invalid metadata, unsupported/missing API markers and
incompatible ranges are excluded. Prereleases require an explicit exact
`--version` pin, which never falls back. Automatic selection cannot downgrade
an installed version; that guard is also checked under the operation lock.
Exact pins may intentionally select an older compatible version. Equal semver
precedence (build metadata) has a deterministic lexical tie break.
The catalog includes API metadata and sorts stable versions semantically before
previews; historical stored listings recover their API marker from immutable
package bytes. The browser shows the actual selected version, running engine,
API and destination. Selection is refreshed on connection, destination changes,
publication and installed-state changes. Installation binds the displayed version
and digest, resolves again locally, then checks the downloaded identity/version,
engine/API manifest and SHA-256 digest before changing configuration or graph.
A selection changed since display requires a refresh. No compatible release and
failed activation preserve the current configuration and graph.
The original publisher identity, immutable release, bearer, local-host, origin
and window restrictions remain in force. Existing exact URL bridge commands
retain their pinned-artifact semantics.
## Reproduction and receipts
From this checkout, with installed development dependencies:
```sh
npm run build
npx vitest run __tests__/extension-releases.test.ts __tests__/extension-marketplace.test.ts __tests__/extension-author.test.ts __tests__/plugins.test.ts __tests__/extension-explore.test.ts __tests__/npm-sdk.test.ts __tests__/cli-install-init.test.ts __tests__/cli-version.test.ts --maxWorkers=2 --minWorkers=1
node --test scripts/validation/extensions-runtime.test.cjs
PLAYWRIGHT_MODULE=/absolute/path/to/playwright COMPAT_OUTPUT=.qa/recovery/compatibility-verified node scripts/validation/extensions-compatibility.cjs
PLAYWRIGHT_MODULE=/absolute/path/to/playwright BROWSER_OUTPUT=.qa/recovery/compat-browser-regression node scripts/validation/marketplace-browser.cjs
```
The browser scripts use local registries and Chrome (`/opt/google/chrome/chrome`)
on Linux. No paid resources or extra model sessions were used. This report's
[JSON receipt](extensions-compatibility-20260922.json) includes exact commands,
source hashes, exits, timestamps, durations, raw log hashes and every headless
subcommand's exit/log hash. Raw receipts/logs are under `.qa/recovery/` in the
saved checkout; output overrides keep earlier evidence intact.
| Check | Result | Duration |
|---|---|---:|
| Final engine/assets/viewer build | exit 0 | 32.724 s |
| Focused installer/registry/author/runtime/retrieval/SDK/CLI tests | 8 files, 43 tests passed; exit 0 | 18.087 s |
| Compiled worker lifecycle, isolation and rollback | 2 tests passed; exit 0 | 7.520 s |
| Generated-extension browser/headless compatibility matrix | 9 acceptance checks, 11 CLI subprocess receipts; exit 0 | 24.301 s |
| Existing publisher/lifecycle/connection browser regression | 11 checks; exit 0 | 14.119 s |
The build ran with the four changes later committed in `79f2d9f` still dirty;
its source bytes match that commit. Final focused, worker and both browser runs
used clean `79f2d9f`. The earlier first matrix attempt at `eab93c3` failed:
root `--version` swallowed an extension pin and printed `1.6.0` with exit 0.
Scoped positional parsing and a CLI regression test fixed this real failure.
That failed receipt/log remains `.qa/recovery/compat-e2e.{json,log}`; it is not
counted as passing evidence. Execution completed without task interruption.
## Acceptance observations
- Signed immutable releases were published in this order: `1.10.0`, `1.9.0`,
`0.5.0`, `20.0.0-beta.1`, `9.0.0` (requires engine `>=9`). The actual engine
is `1.6.0`, API 1. One browser Install after connection selected `1.10.0`.
Publication order and preview precedence did not override compatibility.
- The selected destination was a second Python project without `package.json`.
Its real graph contained `event:order.created → send_receipt`, with the
version-specific `Python event dispatch 1.10.0` edge label. The first
connected project had no extension contribution.
- An extension having only an engine `>=9` release produced a useful failure,
disabled Install, and preserved existing config and graph. Direct bridge
commands and the CLI also failed without mutation.
- Headless automatic installation selected the same `1.10.0`. Exact `9.0.0`
failed with a compatibility error; no version was substituted. Updating a
missing ID also failed.
- Explicit `20.0.0-beta.1` installed only when pinned. Automatic update from
that preview refused a downgrade and preserved config/graph. An explicit
`1.9.0` pin then selected exactly that lower version.
- A compatible but broken `2.0.0` update failed activation and retained
`1.10.0` and its graph. A valid `3.0.0` update succeeded in browser and CLI,
removed stale version labels and still skipped incompatible `9.0.0`.
- Exact artifact URL `1.9.0` and local file `1.10.0` installations remained
exact. Removal cleared their graph contributions.
- Unit checks reject wrong downloaded IDs/versions, unsupported APIs,
incompatible actual manifests, integrity mismatches, duplicate catalog
versions and stale preview bindings. They exercise disjoint engine ranges,
prerelease engine semantics, invalid catalog data and the under-lock
no-downgrade guard.
- The retained browser regression passed signed form publication, ownership,
invalid-signature/malformed-package failure states, selected-project install,
update rollback, stale cleanup, disable/enable/remove and real wrong-window/
wrong-origin postMessage rejection. No browser page errors were recorded.
Desktop and mobile screenshots were visually inspected; selected version,
compatibility and destination are visible and the mobile viewport does not
scroll horizontally. The capture includes local validation-only publisher data.
![Desktop compatible selection](extensions-compatibility-20260922/desktop-selected.png)
![Mobile installed compatible release](extensions-compatibility-20260922/mobile-selected.png)
## Remaining gates
This closes compatible registry resolution for the Linux/local preview, not
full product completion. Next bounded step: process-kill and stale-lock recovery,
including interrupted configuration/database transitions. Actual Windows/macOS,
hosted HTTPS-to-loopback acceptance, durable registry SQLite/artifact storage,
backup/restart checks and Vercel integration remain unverified.
Drupal extraction/runtime source and the three-corpus evidence were unchanged
and reused: nine selected flow probes, deterministic rebuild and incremental
convergence; Express control graph unchanged. Drupal rebuild overhead remains
**22–30%** versus built-in in the measured runs, with limited samples and coverage.
No exhaustive precision/recall or agent A/B claim is made. Author-kit acceptance
at `8b30afb` remains separate from this generated-template compatibility matrix.
The **4,545 passed / 192 skipped** suite at `07b0a10` predates both later milestones
and is not a current whole-suite result. No hosted CI pass is claimed.
Code-complete: full product partial. Validated: this Linux/local milestone passed.
Hosted preview-ready: unverified. Released: no.
Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

@@ -214,8 +214,10 @@ Per-repository records, hashes and all nine raw responses are under
author tests and a fresh generated-extension publish/install/removal exercise.
See [author acceptance](extensions-author-20260922.md) for its separate evidence
and limits; the original recovery scripts alone did not satisfy this gate.
- The catalog selects the most recently published release. Installation rejects
incompatible engine ranges but does not resolve an older compatible release.
- The compatible-version gap was subsequently closed for Linux/local in
`79f2d9f`: browser and headless registry installs select the highest compatible
stable semver; exact pins and automatic no-downgrade updates are verified.
See [compatible release acceptance](extensions-compatibility-20260922.md).
- Exception rollback is tested. Process termination between config/database
writes and stale `operation.lock` recovery are not completed crash guarantees.
- Only Linux was exercised. Native Windows/macOS installation, worker loading,