docs(rust): resume the redesigns at §2 — D331–D334 #334

Merged
whitlocktech merged 1 commits from docs/rust-step-editor-decisions into main 2026-10-10 03:44:42 +00:00
2 changed files with 68 additions and 28 deletions

View File

@@ -430,6 +430,8 @@ in Rust-Plugins, Rust-Link and Module-Rust, and the three cut over to `main` tog
marker types (§4.5), the chat title conditions (§4.6), and the NPC research (§4.7). marker types (§4.5), the chat title conditions (§4.6), and the NPC research (§4.7).
*Planned 2026-09-27:* all six are in one document, [`PLAN_REDESIGNS.md`](PLAN_REDESIGNS.md), as the org *Planned 2026-09-27:* all six are in one document, [`PLAN_REDESIGNS.md`](PLAN_REDESIGNS.md), as the org
lead chose. Its eleven questions were answered the same day as D188–D198 (its §10). lead chose. Its eleven questions were answered the same day as D188–D198 (its §10).
*Resumed 2026-10-09* after RunicNPC v1.0.0 (D331–D334): the items left are coded first, and every walk
still owed — theirs, the redesigns' in-game rows and §8's re-walk — happens once, at the end (D331).
4. **The cutover**, once the re-walk (§8) passes on Oxide and Carbon. 4. **The cutover**, once the re-walk (§8) passes on Oxide and Carbon.
## 7. Helper plugins (D168) ## 7. Helper plugins (D168)

View File

@@ -8,7 +8,9 @@ they can be read together. **Built so far:** §1, walked 2026-09-28 (§1.9); §5
rig walk still to come (§5.8, D209); §3, built and walked on the rigs and the site 2026-09-29, its in-game rig walk still to come (§5.8, D209); §3, built and walked on the rigs and the site 2026-09-29, its in-game
rows still to come (§3.4); §4, built 2026-09-29 (§4.1). **§6 was spiked on 2026-09-30, and the org lead rows still to come (§3.4); §4, built 2026-09-29 (§4.1). **§6 was spiked on 2026-09-30, and the org lead
chose neither route: Runic Gateway writes its own NPC plugin, RunicNPC, planned in chose neither route: Runic Gateway writes its own NPC plugin, RunicNPC, planned in
[`../../runicnpc/PLAN.md`](../../runicnpc/PLAN.md) (D214–D314), and the rest of this plan waits for it.** [`../../runicnpc/PLAN.md`](../../runicnpc/PLAN.md) (D214–D314), and the rest of this plan waits for it.** RunicNPC v1.0.0 shipped on 2026-10-09, and the plan
resumed with §2 the same day (D331–D334). **Every item left is built, tested and PR'd first; every walk —
theirs and the ones still owed by §3 and §5 — happens together at the end (D331, §9).**
This is a companion to [`PLAN_FIXES.md`](PLAN_FIXES.md) and [`PLAN.md`](PLAN.md). Where they disagree, this This is a companion to [`PLAN_FIXES.md`](PLAN_FIXES.md) and [`PLAN.md`](PLAN.md). Where they disagree, this
document is later and wins. Its decisions continue PLAN_FIXES' numbering at **D188**. document is later and wins. Its decisions continue PLAN_FIXES' numbering at **D188**.
@@ -23,12 +25,13 @@ document is later and wins. Its decisions continue PLAN_FIXES' numbering at **D1
| 6 | NPCs — now RunicNPC, its own plan ([`runicnpc/PLAN.md`](../../runicnpc/PLAN.md)) | §4.7 | **runicnpc-rust**, Rust-Plugins, Rust-Link, Module-Rust, installer | | 6 | NPCs — now RunicNPC, its own plan ([`runicnpc/PLAN.md`](../../runicnpc/PLAN.md)) | §4.7 | **runicnpc-rust**, Rust-Plugins, Rust-Link, Module-Rust, installer |
| 11 | First-class optional plugins: Economics, Backpacks, RaidableBases (Kits stays required) | — (added 2026-09-28) | Rust-Plugins, Module-Rust, installer, Android-app | | 11 | First-class optional plugins: Economics, Backpacks, RaidableBases (Kits stays required) | — (added 2026-09-28) | Rust-Plugins, Module-Rust, installer, Android-app |
**Protocol.** Every wire change here joins **protocol 13**, which is still unreleased on `edge` in all three **Protocol.** §1, §3, §4 and §5 joined **protocol 13**, which shipped on 2026-10-09 with RunicNPC v1.0.0
repos. [`PLAN_FIXES.md`](PLAN_FIXES.md) §5 already lists the inventory verb, ZoneManager's flags, zone (bundle 2026.10.09). The wire changes still to come, §2's and §11's, **open protocol 14** on `edge` and are
options and the new tally fields under it, so this adds no bump (§7). released together once, after the end-of-plan walk (D332, §7).
**Core.** §2 is mostly core's editor, which is game-agnostic and serves Module-uo too. Its contract **Core.** §2 is mostly core's editor, which is game-agnostic and serves Module-uo too. Its contract
additions are **MODULE_API 1.11.0 → 1.12.0**, additions only (§8). The same proof website#209 ran for 1.11.0 additions are **MODULE_API 1.12.0 → 1.13.0**, additions only (§8; 1.12.0 went to Events' `progress()`,
website#210). The same proof website#209 ran for 1.11.0
applies: Module-uo's frozen-manifest job and its suites, run against the new core. applies: Module-uo's frozen-manifest job and its suites, run against the new core.
--- ---
@@ -287,7 +290,9 @@ and must leave Module-uo exactly as it is.
- **No type tags.** `ParamField` stops printing ` · {type}` and the bare `*`. A required field says so in - **No type tags.** `ParamField` stops printing ` · {type}` and the bare `*`. A required field says so in
words only when it is empty at save time. words only when it is empty at save time.
- **Each type gets its control:** a toggle for `boolean`, a number field with the declared range beside it for - **Each type gets its control:** for `boolean`, a toggle when the param is required and three buttons side by
side, **[Not set] [Yes] [No]**, when it is optional, because "not set" is a real third state there — the
action's own default — and a two-state toggle would save No for every field nobody touched (D334); a number field with the declared range beside it for
`int` and `float`, a date picker for `datetime`, and a text box only for `string` without a source. `int` and `float`, a date picker for `datetime`, and a text box only for `string` without a source.
- **`core.lease` renders the chosen lease's own form.** The lease is picked by its **label**. The step then - **`core.lease` renders the chosen lease's own form.** The lease is picked by its **label**. The step then
shows the value as the lease's type (a toggle for a boolean lease, a number with the lease's `min`–`max` shows the value as the lease's type (a toggle for a boolean lease, a number with the lease's `min`–`max`
@@ -295,7 +300,7 @@ and must leave Module-uo exactly as it is.
`target.source`** (F11, never built: today the editor reads only `param.source`), and the minutes with the `target.source`** (F11, never built: today the editor reads only `param.source`), and the minutes with the
lease's `maxDurationMs` shown beside them. lease's `maxDurationMs` shown beside them.
- **Examples.** Core's own examples become game-neutral (§0.9). A lease may declare an optional `example` for - **Examples.** Core's own examples become game-neutral (§0.9). A lease may declare an optional `example` for
its value (**MODULE_API 1.12.0**, §8), and `target.example` already exists, so the examples on a lease step its value (**MODULE_API 1.13.0**, §8), and `target.example` already exists, so the examples on a lease step
are that lease's. are that lease's.
### 2.2 A phase that holds a timed step (U-6) ### 2.2 A phase that holds a timed step (U-6)
@@ -303,7 +308,7 @@ and must leave Module-uo exactly as it is.
A phase with no advance rule ends when its steps finish, and teardown gives a lease back at once. So the A phase with no advance rule ends when its steps finish, and teardown gives a lease back at once. So the
"10 minutes" of a lease lasted one second. The fix is to make the duration visible: "10 minutes" of a lease lasted one second. The fix is to make the duration visible:
- A param may declare **`duration: 'minutes'`** (**MODULE_API 1.12.0**). `core.lease`'s `minutes` is one, - A param may declare **`duration: 'minutes'`** (**MODULE_API 1.13.0**). `core.lease`'s `minutes` is one,
and so are `rust.zone.open`'s `minutes` and the other modules' equivalents. and so are `rust.zone.open`'s `minutes` and the other modules' equivalents.
- When a timed step is added to a phase that has **no advance rule**, the editor gives the phase - When a timed step is added to a phase that has **no advance rule**, the editor gives the phase
**`advance: { after: '<the longest duration in the phase>m' }`**, visibly, and the author may change it. **`advance: { after: '<the longest duration in the phase>m' }`**, visibly, and the author may change it.
@@ -327,16 +332,29 @@ choice.**
- **Zones.** `rust.zone.open` gains `enterMessage`, `leaveMessage` and `delivery`. The bridge no longer passes - **Zones.** `rust.zone.open` gains `enterMessage`, `leaveMessage` and `delivery`. The bridge no longer passes
the messages to ZoneManager for its own zones. It subscribes to ZoneManager's `OnEnterZone` and `OnExitZone` the messages to ZoneManager for its own zones. It subscribes to ZoneManager's `OnEnterZone` and `OnExitZone`
and sends them itself, as chat or as a popup, only for the zones in its registry. This also gives F12's and sends them itself, as chat or as a popup, only for the zones in its registry. This also gives F12's
"row 5 cannot show an enter message" (PLAN_FIXES, the step-2 walk) a message to show. "row 5 cannot show an enter message" (PLAN_FIXES, the step-2 walk) a message to show. **Built with §3**
- **Rewards.** The reward actions' message to the player (`rust.kit.entitle` and the other `eventRewards.js` (§3.4), so §2 leaves it alone.
steps that tell a player what they won) gains the same `delivery`. - **Rewards (D333).** There was no in-game reward message to give a `delivery` to: a reward's only notice
was core's engagement notification (`rust.kit.entitled`). So the message is new. `rust.kit.entitle` gains
an optional **`message`** and **`delivery`**. Alice comes second and is rewarded kit `vip`: if she is
online she is told at once, in chat or a popup — "You earned kit vip — type /kit vip" — and if she is
offline she is told when she next wakes up on that server, since the grant already waits for her.
- A blank `message` sends nothing, so a step saved before §2 behaves exactly as it did. `{kit}` in the
text is the kit's name. Only linked recipients have a grant, so only they are told.
- The notice rides `perm.sync` like the credit it belongs to (PROTOCOL §16.3): a new `notices` field,
the site's whole set of untold notices for that server, each `{key, steamId, message, delivery}`,
keyed by run and step. The plugin tells each player once, keeps the keys it has told, and reports
them back (`noticesTold`), so the site marks the grant row told and stops sending it.
- A grant withdrawn before its player came back takes its notice with it: nobody is told about a
reward that is no longer theirs.
- Protocol 14 (D332). An older plugin ignores `notices`; an older site sends none.
- **Without PopupNotifications** a popup falls back to chat. The step editor says so beside the choice when the - **Without PopupNotifications** a popup falls back to chat. The step editor says so beside the choice when the
server's hello reports PopupNotifications absent, as `rust.options.delivery` already does. server's hello reports PopupNotifications absent, as `rust.options.delivery` already does.
### 2.5 The kit weekend as a template (D164) ### 2.5 The kit weekend as a template (D164)
There is no template concept anywhere today. **D192: core gains `api.registerEventTemplates`** There is no template concept anywhere today. **D192: core gains `api.registerEventTemplates`**
(**MODULE_API 1.12.0**), which any module can use: a module declares a named skeleton (phases, steps, params filled in, and a short list (**MODULE_API 1.13.0**), which any module can use: a module declares a named skeleton (phases, steps, params filled in, and a short list
of the inputs the author supplies). The editor's "New event" screen offers the skeletons, asks for their of the inputs the author supplies). The editor's "New event" screen offers the skeletons, asks for their
inputs, and opens an ordinary draft. Nothing about a template survives into the definition, so it is purely an inputs, and opens an ordinary draft. Nothing about a template survives into the definition, so it is purely an
authoring shortcut and the runner never sees it. authoring shortcut and the runner never sees it.
@@ -355,15 +373,18 @@ with `advance: { after }` equal to the duration and two steps:
"N linked players have already used this kit" needs a bulk read the plugin does not have (§0.8). So there is a "N linked players have already used this kit" needs a bulk read the plugin does not have (§0.8). So there is a
new verb, **`kits.uses`**: `{kit, steamIds[]}` in, and `{max, cooldown, exhausted, onCooldown}` out (counts, new verb, **`kits.uses`**: `{kit, steamIds[]}` in, and `{max, cooldown, exhausted, onCooldown}` out (counts,
not a list). It is main thread, capped at the site's linked-player count for that server (the same bound as not a list). It is main thread, capped at the site's linked-player count for that server (the same bound as
the sync's). the sync's). It is **protocol 14** (D332): against a protocol-13 server the note is simply left off.
The warning reaches the core editor through an **optional `note` on an option row** (**MODULE_API 1.12.0**). The warning reaches the core editor through an **optional `note` on an option row** (**MODULE_API 1.13.0**).
When the chosen option carries one, the editor shows it under the field. `rust.options.grouppermissions` When the chosen option carries one, the editor shows it under the field. `rust.options.grouppermissions`
attaches the note to a `kits.*` target: "Kit `vip`: 2 uses, 24 h cooldown — 9 of 41 linked players have used attaches the note to a `kits.*` target: "Kit `vip`: 2 uses, 24 h cooldown — 9 of 41 linked players have used
it up. The weekend's extra use (step 2) is what lets them take it again." it up. The weekend's extra use (step 2) is what lets them take it again."
### 2.7 The walk ### 2.7 The walk
**Deferred to the end-of-plan walk (D331, §9).** The rows, for that walk, plus D333's reward message (online
and on next wake, chat and popup, and a withdrawn grant that tells nobody):
Author a kit weekend from the template on each rig; a lease step with the phase's advance removed (the warning Author a kit weekend from the template on each rig; a lease step with the phase's advance removed (the warning
shows); a draft edited after publishing (Start asks); a boolean lease (a toggle); and a Module-uo event opened shows); a draft edited after publishing (Start asks); a boolean lease (a toggle); and a Module-uo event opened
in the same editor, which must be unchanged apart from the controls. in the same editor, which must be unchanged apart from the controls.
@@ -435,7 +456,7 @@ Built on `edge` as Rust-Plugins `feat/zones-domes`, Module-Rust `feat/zones-dome
- **Where the flags are ticked (D210).** Core's step editor holds one value per field: a text box, a number, - **Where the flags are ticked (D210).** Core's step editor holds one value per field: a text box, a number,
a yes/no, a date, or one dropdown. It has no checkbox list and no slot for a module's own button, and a yes/no, a date, or one dropdown. It has no checkbox list and no slot for a module's own button, and
MODULE_API 1.12.0 (§8) adds neither. So the checkboxes are on a new page, **Admin → Rust zone presets**, MODULE_API 1.13.0 (§8) adds neither. So the checkboxes are on a new page, **Admin → Rust zone presets**,
and the step's **Options** field is one line of text (`NoBuild, NoPlayerLoot, radiation=10`). The field's and the step's **Options** field is one line of text (`NoBuild, NoPlayerLoot, radiation=10`). The field's
dropdown lists the presets, and **each row's value is the preset's line**, so picking one writes that dropdown lists the presets, and **each row's value is the preset's line**, so picking one writes that
line into the field. Core already writes a dropdown's pick into the free-text field beside it, so this line into the field. Core already writes a dropdown's pick into the free-text field beside it, so this
@@ -802,24 +823,28 @@ beyond it.
--- ---
## 7. Protocol 13, what this adds ## 7. Protocols 13 and 14, what this adds
All of these are additions to the unreleased protocol 13. PROTOCOL.md §19 gains a section for each. The rows for §1, §3 and §5 were additions to protocol 13, which shipped on 2026-10-09; PROTOCOL.md §19 has a
section for each. **§2's two rows open protocol 14 (D332)**, which §11 joins, and PROTOCOL.md §20 gains
them. §6's row was never built: RunicNPC replaced route A.
| Change | Direction | § | | Change | Direction | § |
|---|---|---| |---|---|---|
| `perm.inventory` / its paged reply (owners, groups with parents, users, leased) | site → game | 1.2 | | `perm.inventory` / its paged reply (owners, groups with parents, users, leased) | site → game | 1.2 |
| `perm.sync`: groups carry `parent`; `managed` and the foreign report removed | site → game | 1.2 | | `perm.sync`: groups carry `parent`; `managed` and the foreign report removed | site → game | 1.2 |
| `kits.uses` / its reply | site → game | 2.6 | | `kits.uses` / its reply — **protocol 14** | site → game | 2.6 |
| hello: `zoneManager: { version, flags[] }` (from the zone helper); `zoneDomes: { loaded, version }` and the domes helper's state | game → site | 3.1, 3.2 | | hello: `zoneManager: { version, flags[] }` (from the zone helper); `zoneDomes: { loaded, version }` and the domes helper's state | game → site | 3.1, 3.2 |
| `world.zone`: `flags`, `settings`, `enterMessage`, `leaveMessage`, `delivery`, `dome: { type, stack }`; reason `bad-option` | site → game | 2.4, 3.1, 3.2 | | `world.zone`: `flags`, `settings`, `enterMessage`, `leaveMessage`, `delivery`, `dome: { type, stack }`; reason `bad-option` | site → game | 2.4, 3.1, 3.2 |
| the reward verbs' player message: `delivery` | site → game | 2.4 | | `perm.sync`: `notices` (the reward message, D333), and the report's `noticesTold` — **protocol 14** | site ⇄ game | 2.4 |
| `world.place` for an NPC (the verb behind `rust.npc.place`): `kit`, `name`, if route A is chosen | site → game | 6 | | ~~`world.place` for an NPC~~ — not built; RunicNPC (D214) | — | 6 |
| `player.tally`: `animalKills`, `weaponKills`, `headshots`, `bestPvpM`, `bestPveM`, `apcKills`, `heliKills`, `crafted`, `built`, `repaired`, `healed`, `rockets`, `explosives`, `missions` | game → site | 5.1 | | `player.tally`: `animalKills`, `weaponKills`, `headshots`, `bestPvpM`, `bestPveM`, `apcKills`, `heliKills`, `crafted`, `built`, `repaired`, `healed`, `rockets`, `explosives`, `missions` | game → site | 5.1 |
## 8. MODULE_API 1.12.0 (core, website `main`) ## 8. MODULE_API 1.13.0 (core, website `main`)
Additions only, so Module-uo, declared `^1.10.0`, is unaffected, and that is proven the way 1.11.0 was. Planned as 1.12.0; that number went to Events' `progress()` (website#210) while this plan waited for
RunicNPC, so these are 1.13.0. Additions only, so Module-uo, declared `^1.10.0`, is unaffected, and that is
proven the way 1.11.0 was.
- `registerEventTemplates` (§2.5). - `registerEventTemplates` (§2.5).
- A param's optional `duration: 'minutes'` (§2.2). - A param's optional `duration: 'minutes'` (§2.2).
@@ -828,7 +853,10 @@ Additions only, so Module-uo, declared `^1.10.0`, is unaffected, and that is pro
## 9. Order of building ## 9. Order of building
Each item is built on `edge`, walked on both rigs, and PR'd with its spec, like steps 1 and 2: Each item is built on `edge` and PR'd with its spec, like steps 1 and 2. Items 1–4 were also walked as they
were built; **from item 6 on, nothing is walked until every item is coded (D331)**. Code that runs in the
game is still compiled on both rigs before its PR, and a rig spike that a design depends on (§11's source
pulls) is research, not a walk, so it still comes first:
1. **The permission manager** (§1). It is the largest, and §3's exemptions point at it. 1. **The permission manager** (§1). It is the largest, and §3's exemptions point at it.
2. **Chat titles** (§5), including the mission hook. 2. **Chat titles** (§5), including the mission hook.
@@ -841,7 +869,9 @@ Each item is built on `edge`, walked on both rigs, and PR'd with its spec, like
7. **The first-class optional plugins** (§11): Economics, then Backpacks, then RaidableBases, each starting 7. **The first-class optional plugins** (§11): Economics, then Backpacks, then RaidableBases, each starting
with its source pull and rig spike. with its source pull and rig spike.
Then PLAN_FIXES §8's re-walk on Oxide and Carbon, and the cutover. **Then one walk, on Oxide and Carbon, of everything still owed (D331):** §2.7; §11's rows; the in-game rows
of §5.7 and §3.4; PLAN_FIXES §8's re-walk, including the Carbon pass of the first player walk. What it finds
is fixed, protocol 14 is released, and the cutover follows.
## 10. Decisions of record ## 10. Decisions of record
@@ -853,7 +883,7 @@ The plan asked eleven questions. The org lead answered them on 2026-09-27, the d
| **D189** | **A group belongs to one server unless an admin shares it** with chosen servers or the whole fleet. The import makes one group per server, even for identical names. The same group across servers is allowed but never assumed. | One group name fleet-wide with per-server contents (the plan's first proposal). | 1.4 | | **D189** | **A group belongs to one server unless an admin shares it** with chosen servers or the whole fleet. The import makes one group per server, even for identical names. The same group across servers is allowed but never assumed. | One group name fleet-wide with per-server contents (the plan's first proposal). | 1.4 |
| **D190** | **An in-game change affects that server only, and auto-adopt applies it without asking.** A grant that reaches more servers gains an exception for that server; a shared group is split, and that server gets its own copy. | Holding a change to a multi-server row for a person under every policy. | 1.6 | | **D190** | **An in-game change affects that server only, and auto-adopt applies it without asking.** A grant that reaches more servers gains an exception for that server; a shared group is split, and that server gets its own copy. | Holding a change to a multi-server row for a person under every policy. | 1.6 |
| **D191** | **ZoneManager's `ignoreflag` permissions are listed like any other permission.** | One collapsed "exempt from zone flags" section. | 1.7 | | **D191** | **ZoneManager's `ignoreflag` permissions are listed like any other permission.** | One collapsed "exempt from zone flags" section. | 1.7 |
| **D192** | **Core gains event templates** (`registerEventTemplates`, MODULE_API 1.12.0), and the kit weekend is the first. | A Rust-only kit-weekend button. | 2.5 | | **D192** | **Core gains event templates** (`registerEventTemplates`, MODULE_API 1.13.0 — planned as 1.12.0, §8), and the kit weekend is the first. | A Rust-only kit-weekend button. | 2.5 |
| **D193** | **A zone's enter and leave messages and a player's reward message get the Chat / Popup choice**, as announcements have. The bridge sends zone messages itself for its own zones. | Popups for announcements only in this step. | 2.4 | | **D193** | **A zone's enter and leave messages and a player's reward message get the Chat / Popup choice**, as announcements have. The bridge sends zone messages itself for its own zones. | Popups for announcements only in this step. | 2.4 |
| **D194** | **ZoneDomes stays the optional dependency (D167 stands).** A domes helper makes its API safe without a player; the bridge re-adds domes after re-creating zones and removes them at expiry and teardown. | The bridge drawing the dome itself (the plan's first proposal). | 3.2 | | **D194** | **ZoneDomes stays the optional dependency (D167 stands).** A domes helper makes its API safe without a player; the bridge re-adds domes after re-creating zones and removes them at expiry and teardown. | The bridge drawing the dome itself (the plan's first proposal). | 3.2 |
| **D195** | **Zone presets are the admins' own**, saved for one server, several, or the fleet. None ship. | Shipped presets (Arena, Safe zone, No building). | 3.1 | | **D195** | **Zone presets are the admins' own**, saved for one server, several, or the fleet. None ship. | Shipped presets (Arena, Safe zone, No building). | 3.1 |
@@ -903,6 +933,15 @@ The §4 build raised one more, answered on 2026-09-29:
| **D219** | **Rust's navmesh is used;** a custom navigation mesh is a later stage, only if needed. | NpcSpawn-style point meshes from the start. | 6, RunicNPC §8 | | **D219** | **Rust's navmesh is used;** a custom navigation mesh is a later stage, only if needed. | NpcSpawn-style point meshes from the start. | 6, RunicNPC §8 |
| **D220** | **RunicNPC is built and tested in stages before this plan resumes, then `module-rust` requires it.** | Building it alongside items 6 and 7. | 9, RunicNPC §9 | | **D220** | **RunicNPC is built and tested in stages before this plan resumes, then `module-rust` requires it.** | Building it alongside items 6 and 7. | 9, RunicNPC §9 |
The plan resumed on 2026-10-09, after RunicNPC v1.0.0, with four more:
| # | Decision | Rejected | § |
|---|---|---|---|
| **D331** | **Every item left (§2, §11) is coded before anything is walked; then one walk covers it all**, with the walks §3 and §5 still owe and PLAN_FIXES §8's re-walk, and what it finds is fixed before the release. Rig spikes a design depends on, and compiling on both rigs, still happen as each item is built. | Walking each item as it is built, as items 1–4 were. | 9 |
| **D332** | **§2 and §11 open protocol 14 on `edge`, released together once after the end walk.** Protocol 13 shipped on 2026-10-09. | Protocol 14 for §2 alone and 15 for §11; dropping `kits.uses` to keep §2 off the wire. | 7, 11.5 |
| **D333** | **A kit reward can tell its player in game.** `rust.kit.entitle` gains an optional `message` and `delivery`; the notice rides `perm.sync` and is told once, at once or on the player's next wake; a blank message tells nobody. | The engagement notification as the only notice. | 2.4 |
| **D334** | **An optional boolean param is three buttons, [Not set] [Yes] [No]; a required one is a toggle.** | A two-state toggle everywhere, which saves No for a field nobody touched. | 2.1 |
## 11. First-class optional plugins (D199–D202) ## 11. First-class optional plugins (D199–D202)
The org lead named four plugins the module supports as first-class integrations. Kits already is one. The other The org lead named four plugins the module supports as first-class integrations. Kits already is one. The other
@@ -1177,6 +1216,5 @@ The org lead answered §11.4.4's three questions the same day:
### 11.5 Protocol ### 11.5 Protocol
These are new verbs, events and hello fields. If they are built before the cutover they join the unreleased These are new verbs, events and hello fields. **They join protocol 14 (D332)**, which §2 opens: protocol 13
protocol 13 like everything else here; if the cutover comes first, they open protocol 14. Which one is decided shipped on 2026-10-09, before §9 reached item 7.
when §9 reaches item 7.