diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index d4d5deb2..0706048c 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -61,9 +61,9 @@ jobs:
# The tag is written twice, on `uses:` and as the input, because a called workflow cannot see its
# own ref. The called workflow refuses to run unless the two are identical, so they stay one
# fact. It must match [tool.idfkit.governance] level in pyproject.toml; advance all three together.
- uses: idfkit/idfkit-conformance/.github/workflows/check-consumer.yml@governance-2026.18
+ uses: idfkit/idfkit-conformance/.github/workflows/check-consumer.yml@governance-2026.20
with:
- governance_level: governance-2026.18
+ governance_level: governance-2026.20
pins:
name: pins
diff --git a/.github/workflows/rehearse-candidate.yml b/.github/workflows/rehearse-candidate.yml
index a7236ec9..e591a1e1 100644
--- a/.github/workflows/rehearse-candidate.yml
+++ b/.github/workflows/rehearse-candidate.yml
@@ -41,9 +41,9 @@ permissions:
jobs:
rehearse:
- uses: idfkit/idfkit-conformance/.github/workflows/rehearse.yml@governance-2026.18
+ uses: idfkit/idfkit-conformance/.github/workflows/rehearse.yml@governance-2026.20
with:
- governance_level: governance-2026.18
+ governance_level: governance-2026.20
consumer: idfkit-developers
library: ${{ inputs.library }}
candidate_ref: ${{ inputs.candidate_ref }}
diff --git a/docs/explanation/consumers.md b/docs/explanation/consumers.md
index c10cc24e..20a24e62 100644
--- a/docs/explanation/consumers.md
+++ b/docs/explanation/consumers.md
@@ -46,7 +46,7 @@ of the other language. For the parity side of the same governance, see
-Generated from [`governance/consumers.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.18/governance/consumers.toml) at `governance-2026.18`, the governance tag this
+Generated from [`governance/consumers.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.20/governance/consumers.toml) at `governance-2026.20`, the governance tag this
release pins. Correct the register and regenerate; a correction made on this page would be
overwritten, and it would never reach a consumer's self-check.
@@ -79,7 +79,7 @@ states it. A lag of "none" means nothing is wrong: it is the normal state.
| `envelop` | JavaScript | the scoped packages | declared directly | `package.json` at `dependencies["@idfkit/core"]`
`package.json` at `dependencies["@idfkit/schemas"]`
`package.json` at `dependencies["@idfkit/language"]`
`package.json` at `dependencies["@idfkit/weather"]` | not yet, [tracked](https://github.com/idfkit/idfkit-app/issues/226) |
| `idfkit-shoebox` | JavaScript | the scoped packages | declared directly | `package.json` at `dependencies["@idfkit/core"]`
`package.json` at `dependencies["@idfkit/schemas"]`
`package.json` at `dependencies["@idfkit/weather"]` | none |
| `idfkit-mcp-deployment` | Python | `idfkit` | in a container image | `cdk.json` at `context.idfkit_mcp_ref` (idfkit-mcp via `idfkit-mcp`) | none |
-| `idfkit-plugin` | Python | `idfkit` | fetched when an editor starts | `.mcp.json` at `mcpServers.idfkit.args[0]` (idfkit-mcp via `idfkit-mcp`)
`.lsp.json` at `idfkit.args[1]` (idfkit-lsp via `idfkit-lsp`), range | not yet, [tracked](https://github.com/idfkit/idfkit-plugin/issues/17) |
+| `idfkit-plugin` | Python | `idfkit` | fetched when an editor starts | `.mcp.json` at `mcpServers.idfkit.args[0]` (idfkit-mcp via `idfkit-mcp`)
`.lsp.json` at `idfkit.args[1]` (idfkit-lsp via `idfkit-lsp`) | none |
## Recorded, and governed by nothing here { #ungoverned }
diff --git a/docs/explanation/naming-map.md b/docs/explanation/naming-map.md
index 64a766dc..26f2f36c 100644
--- a/docs/explanation/naming-map.md
+++ b/docs/explanation/naming-map.md
@@ -80,8 +80,8 @@ ledger, where permanent single-language capabilities are recorded as such.
Generated from
-[`governance/naming.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.18/governance/naming.toml)
-at `governance-2026.18`, the governance tag this release pins. It governs `idfkit` and
+[`governance/naming.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.20/governance/naming.toml)
+at `governance-2026.20`, the governance tag this release pins. It governs `idfkit` and
`@idfkit/core` and `@idfkit/weather` and `@idfkit/language`, and it is read at a pinned
governance-YYYY.N tag of idfkit-conformance, never the default branch. Correct the
register and regenerate; a correction made on this page would be overwritten, and it
@@ -3824,8 +3824,8 @@ one language under schedule pressure.
| Capability | npm package | Subpath | Mirrors | Tier | Built |
| ---------- | ----------- | ------- | ------- | ---- | ----- |
-| schedules | `@idfkit/schedules` | `idfkit/schedules` | `idfkit.schedules` | 2 | not yet |
-| geometry, geometry builders, surface matching, zoning | `@idfkit/geometry` | `idfkit/geometry` | `idfkit.geometry`, `idfkit.geometry_builders`, `idfkit.surface_matching`, `idfkit.zoning` | 2 | not yet |
+| schedules | `@idfkit/schedules` | `@idfkit/idfkit/schedules` | `idfkit.schedules` | 2 | not yet |
+| geometry, geometry builders, surface matching, zoning | `@idfkit/geometry` | `@idfkit/idfkit/geometry` | `idfkit.geometry`, `idfkit.geometry_builders`, `idfkit.surface_matching`, `idfkit.zoning` | 2 | not yet |
## What the gate refuses
diff --git a/docs/explanation/parity.md b/docs/explanation/parity.md
index 20622599..e36783bf 100644
--- a/docs/explanation/parity.md
+++ b/docs/explanation/parity.md
@@ -79,8 +79,8 @@ Ids get added and deprecated. They do not get renamed.
Generated from
-[`governance/parity.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.18/governance/parity.toml)
-at `governance-2026.18`, the governance tag this release pins. Correct the ledger and
+[`governance/parity.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.20/governance/parity.toml)
+at `governance-2026.20`, the governance tag this release pins. Correct the ledger and
regenerate; a correction made on this page would be overwritten, and it would never
reach either library's CI gate.
@@ -291,7 +291,7 @@ possibility.
Installation differs, and the difference is deliberate. `pip install idfkit` installs weather and
its station index unconditionally, because Python extras gate dependencies rather than files, so a
- Python reader has weather whether or not they wanted it. `npm install idfkit` installs neither:
+ Python reader has weather whether or not they wanted it. `npm install @idfkit/idfkit` installs neither:
weather is an opt-in peer there, added with `npm install @idfkit/weather`. Both libraries ship
their own index once installed and neither retrieves one to get started (FR-043, FR-075,
research R11). A JavaScript reader who follows a weather page without installing that package
diff --git a/pyproject.toml b/pyproject.toml
index 204e3dcf..123bb39d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -73,7 +73,7 @@ level = "conformance-2026.12"
# through the duplicated scripts/_governance_source.py. 2026.18 is the first tag carrying
# governance/consumers.toml (feature 004); the consumer-register job in docs.yml pins the same tag.
[tool.idfkit.governance]
-level = "governance-2026.18"
+level = "governance-2026.20"
# Documentation artifact level the TypeScript half of the site renders from, as an immutable tag
# in idfkit-js. It carries the TypeScript examples the pages include and the TypeDoc JSON the