Commit Graph

112 Commits

Author SHA1 Message Date
6802dbf5f9 Merge pull request 'feat(rust): Dynamic PVP's zones on the feed and the map (PLAN_REDESIGNS §14.3.3)' (#46) from feat/dynamic-pvp into edge
Reviewed-on: #46
2026-10-15 11:17:59 +00:00
549b3a5ffd feat(rust): Dynamic PVP's zones on the feed and the map (PLAN_REDESIGNS §14.3.3)
All checks were successful
PR Checks / client-build (pull_request) Successful in 25s
PR Checks / server-tests (pull_request) Successful in 31s
PR Checks / frozen-manifest (pull_request) Successful in 44s
Stage 4 of the §14.3 integration plan, on protocol 14 (docs
rust-link/PROTOCOL.md §20.7).

- pvp.zone.created is a public kind, pvp.zone.deleted a staff kind. Each row
  is read per viewer by the new dynamicPvp.js: grid for everyone, the event's
  name only for Dynamic PVP's own vanilla events, position and zone id for
  staff only.
- The feed's world filter carries the opening: "A PvP zone opened around the
  downed patrol helicopter · G7 · for 10 min". It names nobody.
- The map gains a fifth layer, `pvp` (PvP zones), public by default with its
  own audience in Admin → Rust visibility, drawn as a red ring with its
  event's name.
- Server settings' plugin line names Dynamic PVP; the swagger schemas and
  route descriptions carry the layer and the integration (fragment
  regenerated); ci/bundle.json ships dynamicPvp.js; README lists it.

Tests: server 611/611 (dynamicPvp.test.js new, catalogue and map extended)
and every check; client 89/89 (feed and map tooltip), build and externals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-15 06:12:07 -05:00
b5f7fa0f13 Merge pull request 'feat(rust): TruePVE in the zone step — no PvP protection, or a ruleset (PLAN_REDESIGNS §14.3.2)' (#45) from feat/truepve-zone into edge
Reviewed-on: #45
2026-10-15 11:06:11 +00:00
e3cc95f8ab feat(rust): TruePVE in the zone step — no PvP protection, or a ruleset (PLAN_REDESIGNS §14.3.2)
All checks were successful
PR Checks / client-build (pull_request) Successful in 24s
PR Checks / frozen-manifest (pull_request) Successful in 44s
PR Checks / server-tests (pull_request) Successful in 7m23s
Stage 3 of the §14.3 integration plan (D362, D368), on protocol 14 (docs
rust-link/PROTOCOL.md §20.6).

- rust.zone.open gains noPvpProtection (boolean) and pvpRuleset (string),
  sent as world.zone's truePve { exclude: true } or { ruleset }.
- Both set, a name over 64 characters, or a server whose hello says TruePVE
  is not loaded is refused for good, at verify too. A server that has not
  said is left to the plugin, as a dome is.
- truepve-missing and truepve-ruleset are permanent failures, with the
  plugin's words.
- The zone servers list carries each server's truePve from hello; Server
  settings' plugin line says whether TruePVE is loaded; the integrations
  schema documents it (swagger fragment regenerated).
- README lists TruePVE among the optional plugins.

Tests: five new in zones.test.js; server 603/603 and all checks, client
84/84 and the build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-15 05:48:00 -05:00
4af731288a feat: TruePVE in the zone step (PLAN_REDESIGNS §14.3.2, WIP)
Stage 3 of the §14.3 integration plan (D362, D368): world.zone's optional
truePve ({exclude: true} or {ruleset}), all or nothing, unmapped on every
path that erases one of our zones, with truepve.json for erases while
TruePVE is away. Docs and PRs still to come.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-15 03:03:36 -05:00
176ded67a8 Merge pull request 'feat(rust): Rust's own world events — feed, credit rule, triggers, Call a world event (PLAN_REDESIGNS §14.3.1)' (#44) from feat/world-events into edge
Reviewed-on: #44
2026-10-15 07:19:10 +00:00
e7d5c8ed1a feat(rust): Rust's own world events — feed, credit rule, triggers, Call a world event (PLAN_REDESIGNS §14.3.1)
All checks were successful
PR Checks / client-build (pull_request) Successful in 31s
PR Checks / server-tests (pull_request) Successful in 36s
PR Checks / frozen-manifest (pull_request) Successful in -1m32s
The site half of stage 1, on protocol 14:

- server/worldEvents.js: the 24 types, D372's four credit rules, the grid
  from the map's geometry (none off the map), and the per-viewer reading.
- The feed serves `world.event` (a public kind): an unknown type is staff's;
  the event and its grid are public; names only for the presence audience
  (D376); Steam ids and positions only for staff (D353). A downed one carries
  `credited`/`creditedCount` by the server's rule. Client lines for all 24
  types and a World events filter.
- rust_servers.credit_rule (blow, last, most, all; default blow), set on the
  server's settings. Ingest counts heli_kills (patrol helicopters and
  Chinooks, D379) and apc_kills from `world.event` by that rule, so the line
  and Rotorbane / Tankbreaker agree. A protocol-13 tally's heliKills/apcKills
  still add as before.
- The tally's cratesHacked / dropsLooted → crates_hacked / drops_looted;
  title categories Safecracker and Scavenger (D356); leaderboard columns
  Crates hacked and Drops looted, sortable (D377).
- 24 engagement triggers rust.world.<event> (D355): ceiling everyone,
  cooldown subject the server and event (crates add where), names only.
- server/eventWorldCall.js: rust.world.call, "Call a world event"
  (risk change, reversible none, budget rust.world.calls). A position for an
  airdrop or a patrol helicopter only; the Chinook takes none (D378).

Server 585/585 (22 new in test/worldEvents.test.js), client 84/84, every
check; booted against the pinned core (43 triggers, 12 actions, 10 budgets,
20 option sources), routes.manifest unchanged at 89. Engagement manifest and
swagger fragment regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-15 00:39:00 -05:00
f65d96ebb6 Merge pull request 'chore(ci): pin the core to website main at #213's merge' (#43) from chore/core-ref-213 into edge
Reviewed-on: #43
2026-10-14 09:35:21 +00:00
11d32436a4 chore(ci): pin the core to website main at #213's merge
All checks were successful
PR Checks / client-build (pull_request) Successful in 28s
PR Checks / server-tests (pull_request) Successful in 37s
PR Checks / frozen-manifest (pull_request) Successful in -1m34s
website#213 (MODULE_API 1.14.0, the `multiple` param) merged as a981b2b.
Its tree is identical to the branch head 743f1bc this was pinned to, so
routes.manifest.json is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-14 04:18:53 -05:00
aefd752372 Merge pull request 'feat(rust): permissions as event rewards — lend or give any registered permission (PLAN_REDESIGNS §12)' (#42) from feat/rust-perm-rewards into edge
Reviewed-on: #42
2026-10-13 01:03:39 +00:00
63c82d5a2f feat(rust): permissions as event rewards — lend or give any registered permission (PLAN_REDESIGNS §12)
All checks were successful
PR Checks / client-build (pull_request) Successful in 20s
PR Checks / server-tests (pull_request) Successful in 27s
PR Checks / frozen-manifest (pull_request) Successful in -1m32s
D342-D346 (docs#342). Two steps over the permission mirror's own tables, so
no plugin, sidecar or protocol change:

- rust.perm.lend, "Permissions until the event ends": a kit reward's lease,
  one rust_perm_run_grants row per recipient per permission, the message on
  one row each; change/ledger with rust.kit.entitle's revert and reconcile;
  budget rust.permissions.
- rust.perm.give, "Permissions for good": a standing rust_perm_grants row per
  website user per permission, scoped to the step's server, source `event`,
  note "event run <run>, step <step>"; a grant already there is left alone,
  and a retry's own grants are counted as given; the message rides a
  notice-only run-grant row; irreversible/none; budget rust.permissions.kept.
- Both: several permissions through core's `multiple` param (MODULE_API
  1.14.0, at most 10); a required "I am sure" toggle refused unticked in the
  dry run and at run time, naming the permissions (D343); a permission the
  server's catalogue lacks refused by name; a blank message tells nobody.
- rust.options.permissions: the enabled servers' catalogues, grouped by the
  registering plugin (by prefix when none), sorted plugin then permission
  without case, a row noted "Only on X" when not on every server.
- Permission manager: an event-given grant shows "given by event run N,
  step M"; staff turn it off like any grant.
- coreApi ^1.14.0; ci/core-ref.json pinned to website#213's head until it
  merges; engagement-triggers.json regenerated; routes.manifest.json
  unchanged (no new routes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-12 15:49:44 -05:00
89557ddf66 Merge pull request 'feat(rust): Backpacks — staff and player views, the Bigger backpack step (PLAN_REDESIGNS §11.3)' (#41) from feat/rust-backpacks into edge
Reviewed-on: #41
2026-10-12 19:41:20 +00:00
e4591af906 feat(rust): Backpacks — staff and player views, the Bigger backpack step (PLAN_REDESIGNS §11.3)
All checks were successful
PR Checks / server-tests (pull_request) Successful in 37s
PR Checks / frozen-manifest (pull_request) Successful in 1m0s
PR Checks / client-build (pull_request) Successful in 7m23s
The site half of §11.3.2, on protocol 14:

- `rust.backpack.size` ("Bigger backpack"): a kit reward with a different
  permission (D337) — one rust_perm_run_grants row per website user with
  backpacks.size.N, no kit, no credit; the perm mirror pushes it and the run's
  revert deletes it. risk change, reversible ledger, a new `rust.backpacks`
  budget, rust.kit.entitle's recipient modes including `linked`. Refused with
  "Backpacks is not installed on this server" in the dry run too (D199), and a
  size the server does not offer is refused by name. Its message is never
  silent: empty is the take-back warning (D338).
- `rust.options.backpacksizes`: each server's sizes above its smallest, from
  the last hello, grouped by server.
- GET /player/rust/backpacks (own links only, 20 reads a minute) and
  GET /admin/users/:id/rust/backpacks (that user's links only). Live, never
  stored; a stranger's id is a 404 and never reaches the game.
- Client: a shared Backpack panel (pick server and account, open, read once)
  on the account page and the admin user page; the grid draws pages of
  pageSize, each slot named by the game (D340, no icons), blueprints by what
  they make (D341), overflow marked. Backpacks joins the server's mod line.

Server 548/548 (13 new in test/backpacks.test.js), client 79/79 (5 new),
routes.manifest regenerated against the pinned core (89 routes), swagger
fragment regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-12 14:35:55 -05:00
69ec0f6c46 Merge pull request 'feat(rust): Economics — pay coins, balances, staff adjust, the richest (PLAN_REDESIGNS §11.2)' (#40) from feat/protocol-14-economics into edge
Reviewed-on: #40
2026-10-12 12:40:53 +00:00
845caef817 feat(rust): Economics — pay coins, balances, staff adjust, the richest (PLAN_REDESIGNS §11.2)
All checks were successful
PR Checks / server-tests (pull_request) Successful in 31s
PR Checks / client-build (pull_request) Successful in 29s
PR Checks / frozen-manifest (pull_request) Successful in -1m29s
The site half of §11.2.2, on protocol 14:

- `rust.coins.pay` ("Pay coins"): irreversible, reversible none (D335). The
  recipient modes of rust.kit.entitle including `linked`, one payment per
  website user (D103's rule), an optional message with {amount}, a new
  `rust.coins` budget. Refused with "Economics is not installed on this
  server" in the dry run too (D199). Core's key goes to the plugin, so a
  retried step answers `repeat` and pays nobody twice.
- `rust_player_wipe_stats.balance`: the tally's balance, written as a value.
  A nameless balance frame (an offline player) moves nobody's last-seen.
  `economics.wiped` clears the wipe's balances, except at a new save.
- The richest: a Coins leaderboard column on one wipe of a server that
  reports Economics, `sort=balance`, and a `richest` title category
  (Magnate); both rank only above the starting balance (D336).
- GET /player/rust/economics (live, falling back to the last known), and
  GET/POST /admin/users/:id/rust/economics for staff — scoped to the user's
  own links, keyed per submission, an activity row with before and after.
- Client: the account page's Coins, the admin user page's Coins panel with
  its form, the leaderboard column, and Economics in the server's mod line
  (saying when its config could not be read).

Server 535/535 (14 new in test/economics.test.js), client 74/74,
routes.manifest regenerated against the pinned core (87 routes), swagger
fragment regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-12 07:07:05 -05:00
1777cb6ce1 Merge pull request 'chore(ci): re-pin core to website main at #212's merge' (#39) from chore/repin-core-212 into edge
Reviewed-on: #39
2026-10-12 11:41:31 +00:00
a64ae68158 chore(ci): re-pin core to website main at #212's merge
All checks were successful
PR Checks / server-tests (pull_request) Successful in 33s
PR Checks / frozen-manifest (pull_request) Successful in 55s
PR Checks / client-build (pull_request) Successful in 7m23s
website#212 (MODULE_API 1.13.0) merged as ca7ec53, whose tree is the
same as the branch head e58857c this repo was pinned to while it was
open. Only the pin moves; routes.manifest.json is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-12 05:08:39 -05:00
21e40053ab Merge pull request 'feat(rust): the kit weekend, linked rewards, reward messages and the kit warning (protocol 14)' (#38) from feat/protocol-14-step-editor into edge
Reviewed-on: #38
2026-10-12 09:51:57 +00:00
d21a9e2c0d feat(rust): the kit weekend, linked rewards, reward messages and the kit warning (protocol 14)
All checks were successful
PR Checks / client-build (pull_request) Successful in 3m46s
PR Checks / frozen-manifest (pull_request) Successful in 6m12s
PR Checks / server-tests (pull_request) Successful in 7m30s
PLAN_REDESIGNS §2, the Rust half (D164, D192, D332, D333):
- rust.template.kit_weekend (core registerEventTemplates, MODULE_API 1.13.0):
  inputs kit/minutes/message/delivery; one phase advance after the weekend,
  core.lease rust.group.permission default/<kit permission> + rust.kit.entitle
  linked. Steps only where the kit can use them; validated by the real core.
- rust.kit.entitle: recipients 'linked' (every linked player who has played
  on the server, no tally, refused past the bound), optional message ({kit})
  and delivery, stored per row (rust_perm_run_grants.notice*).
- perm.sync notices: the untold set to the picked account, keyed
  run:step:user, in the digest; the report's noticesTold marks them told.
- rust.options.grouppermissions notes a kit's permission rows via kits.uses
  (cached a minute per server; a failure is no note).
- duration: 'minutes' on rust.zone.open and rust.participation.open; the
  group-permission lease's value example is true.
- protocol 13 -> 14, coreApi ^1.13.0; ci/core-ref.json pinned to website#212's
  head while it is open; engagement-triggers.json regenerated (coreApi line).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-12 02:25:06 -05:00
be8c09e6b3 Merge pull request 'feat(rust): RunicNPC required, protocol 13, edge → main (runicnpc 9e step 3, merge 3 of 3)' (#37) from edge into main
All checks were successful
Release / release (push) Successful in -1m42s
Reviewed-on: #37
v0.4.0
2026-10-09 07:22:41 +00:00
65cef3e7c0 Merge pull request 'feat(zones): a blank dome stack is 3 spheres, not 1 (runicnpc 9e, D326)' (#36) from feat/9e-dome-stack-3 into edge
All checks were successful
PR Checks / server-tests (pull_request) Successful in 36s
PR Checks / frozen-manifest (pull_request) Successful in 1m1s
PR Checks / client-build (pull_request) Successful in 7m27s
Reviewed-on: #36
2026-10-09 06:29:26 +00:00
e1789c1df4 feat(zones): a blank dome stack is 3 spheres, not 1 (runicnpc 9e, D326)
All checks were successful
PR Checks / server-tests (pull_request) Successful in 32s
PR Checks / frozen-manifest (pull_request) Successful in 1m13s
PR Checks / client-build (pull_request) Successful in 7m49s
The org lead chose 3 by eye at noon in RunicNPC's 9d player session. The
zone step sends it when its stack is left blank, and the field's hint says
so. The wire is unchanged: the module always sends a stack, and the bridge's
own default for a dome without one stays 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-09 01:24:19 -05:00
4ad38d443b Merge pull request 'fix(swagger): regenerate the fragment for stage 9's runicNpc status field' (#35) from fix/swagger-fragment-stage9 into edge
Reviewed-on: #35
2026-10-07 02:47:36 +00:00
8b6e96086f fix(swagger): regenerate the fragment for stage 9's runicNpc status field
Some checks failed
PR Checks / client-build (pull_request) Successful in 17s
PR Checks / frozen-manifest (pull_request) Failing after 32s
PR Checks / server-tests (pull_request) Successful in 7m32s
RunicNPC stage 9 (#34, D310) added a runicNpc object to the server status
schema in server/swagger/doc.js but did not regenerate swagger-fragment.json,
so check:swagger turned server-tests red on run 38 and edge has been red
since the merge. This is the output of `npm run swagger`, nothing else.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-06 21:46:56 -05:00
1188a3142e Merge pull request 'feat(rust): RunicNPC is required for every Place NPCs step (runicnpc stage 9, D310)' (#34) from feat/runicnpc-stage9 into edge
Reviewed-on: #34
2026-10-07 02:43:32 +00:00
f71a2907fb docs(rust): the NPC picker's comment says what stage 9 kept (D310)
Some checks failed
PR Checks / client-build (pull_request) Successful in 23s
PR Checks / server-tests (pull_request) Failing after 26s
PR Checks / frozen-manifest (pull_request) Successful in 42s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-06 21:34:01 -05:00
d140d5c66d feat(rust): RunicNPC is required for every Place NPCs step (runicnpc stage 9, D310)
A Place NPCs step on a server without RunicNPC, or with one older than the
bridge needs, is refused before it is sent: "<server> needs RunicNPC to place
NPCs, Rust's own scientists included: <why>". Rust's own scientists were the
fallback until now (D243); they need RunicNPC too. Crates are unaffected.

- npcs.model: API_NEEDED rises from 4 to 6, the bridge's RunicNpcApiNeeded, so a
  server the site calls ready is one the bridge will not refuse as runicnpc-old.
  The profile push follows the same floor.
- eventWorld: profileMissing becomes npcMissing, asked for every NPC step.
- Admin → Rust → Servers: each server carries `runicNpc` ({ready, absence,
  version, api}) and a server without one that will do reads "Incomplete" with
  the reason. Swagger documents the field.

The event picker is unchanged in this commit (an open question on the PR).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-06 16:58:30 -05:00
72f6c557d2 Merge pull request 'feat(rust): event NPCs named on the map, and a Place NPCs step's progress line (runicnpc stage 8)' (#33) from feat/runicnpc-stage8 into edge
Reviewed-on: #33
2026-10-06 13:32:43 +00:00
5162496d74 feat(rust): event NPCs named on the map, and a Place NPCs step's progress line (runicnpc stage 8)
All checks were successful
PR Checks / client-build (pull_request) Successful in 20s
PR Checks / server-tests (pull_request) Successful in 25s
PR Checks / frozen-manifest (pull_request) Successful in -1m18s
- rust.npc.place's progress() (MODULE_API 1.12.0, D304). It reports the
  step's NPCs still standing, by its key, of how many it placed, with
  the profile's label: "Bandit: 2 of 3 left". A boss step is its
  health, "Walk Juggernaut: 59%", and a boss's adds are not counted.
  The data comes from the map's live answer, so it costs the game no
  extra ask. A reader who may not see the map's events layer gets no
  line.
- The map (D302, D303):
  - an NPC's tooltip is its name and its event's title, read from
    core's public calendar, which lists only announced events;
  - a boss is bigger and in its own colour, and an add says so;
  - a boss outside any event is in the world layer;
  - a boss's health is removed from what a viewer is sent.
- The world layer's visibility hint mentions those bosses.

coreApi stays ^1.11.0: an older core ignores the optional member, and
the action works without a progress line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-06 08:23:13 -05:00
3c3d154b36 Merge pull request 'feat(rust): loot on the NPC profile form, and the Place NPCs step's "drop loot" switch (runicnpc stage 7)' (#32) from feat/runicnpc-stage7 into edge
Reviewed-on: #32
2026-10-06 07:16:44 +00:00
34ca84f6be fix(rust): the profile list says "own loot" for a profile with a loot table
All checks were successful
PR Checks / server-tests (pull_request) Successful in 27s
PR Checks / frozen-manifest (pull_request) Successful in 49s
PR Checks / client-build (pull_request) Successful in 7m42s
Found on the stage 7 walk: a profile with its own loot read exactly like
one without in the list under the form, where a boss already says
"boss".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-06 01:28:18 -05:00
33c5178ef9 feat(rust): loot on the NPC profile form, and the Place NPCs step's "drop loot" switch (runicnpc stage 7)
The profile form's Loot section (D290-D301):

- what the corpse starts with (Rust's scientist loot, the kit, or
  nothing);
- rows that always roll, each with its chance;
- a pool capped at its picks, with a "nothing" weight;
- which crate the table goes into, and a locked crate's hack time;
- how long the corpse stays.

The site checks the block as RunicNPC does, in its words. Whether an
item exists on a server is RunicNPC's to say on the push.

The Place NPCs step's dropLoot switch (D296), on by default and sent
only when off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-06 00:32:24 -05:00
bb3e25b5d7 Merge pull request 'feat(rust): bosses and passive NPCs on the profile form, and public boss triggers (runicnpc stage 6)' (#31) from feat/runicnpc-stage6 into edge
Reviewed-on: #31
2026-10-06 00:45:19 +00:00
f2ca314d10 feat(rust): bosses and passive NPCs on the profile form, and public boss triggers (runicnpc stage 6)
All checks were successful
PR Checks / client-build (pull_request) Successful in 20s
PR Checks / server-tests (pull_request) Successful in 24s
PR Checks / frozen-manifest (pull_request) Successful in 46s
The profile form's boss box (D273-D277): the bar's distance, where its
lines are said, the spawn and death lines, and phases at health
percentages, each with optional damage, aim, speed, ranges, a kit swap,
adds of another profile and a line. The passive role (D278, D279,
D288): press E answers with a chat line or a window, it moves as its
profile says (now including `stand`), and it starts unhurtable.

The site checks both as RunicNPC does, in its words; a phase's kit is
checked on each server like the profile's own, and its adds must name a
site profile that is not a boss.

Public triggers rust.boss.spawned, rust.boss.phase and rust.boss.killed
(D277) from the bridge's new frames. In the feed, a boss appearing is
public; its death names the killer, so it sits behind the presence
setting; its phases are staff's, as the game tells them only to players
near it (D286). engagement-triggers.json regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-05 10:54:28 -05:00
620ea63b54 Merge pull request 'feat(rust): NPC sides, the faction table, an event's escort, ally and tether (runicnpc stage 5)' (#30) from feat/runicnpc-stage5 into edge
Reviewed-on: #30
2026-10-05 08:38:43 +00:00
11619a4dc6 feat(rust): NPC sides, the faction table, an event's escort, ally and tether (runicnpc stage 5)
All checks were successful
PR Checks / client-build (pull_request) Successful in 31s
PR Checks / server-tests (pull_request) Successful in 39s
PR Checks / frozen-manifest (pull_request) Successful in 58s
RunicNPC stage 5 on the site (docs runicnpc/PLAN.md, D253-D272):

- profiles gain the guard role, faction, relations (its own exceptions),
  alertRadius, turrets, hurtByPlayers, hurtsPlayers and kitUse, checked in
  RunicNPC's order and words, and defaulting to "players only" (D255);
- the faction table: one site-wide table, one row per pair and both ways
  (D254, D268), stored in rust_npc_factions, edited on the NPC profiles page
  (PUT /admin/rust/npcs/factions), pushed to every server with its
  profiles and hashed with them, and a standalone server's own pairs
  adopted at its first push with the site's winning (D244, D251);
- the Place NPCs step takes escort (a Steam id or a {placeholder}), an ally
  (a clan from the new rust.options.clans source, or the team of a player)
  and tether (the zone this event made), for a RunicNPC profile only
  (D269, D270, D272);
- a placement may be held inside a zone (tether, D272);
- the bridge's RunicNPC API floor is 4.

Tests: 488 server, 66 client. routes.manifest.json regenerated against the
pinned core (one route added).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-01 07:58:13 -05:00
b83fa8174c Merge pull request 'feat(rust): RunicNPC profiles, placements, event NPCs and per-profile kills (runicnpc stage 4)' (#29) from feat/runicnpc-stage4 into edge
Reviewed-on: #29
2026-09-30 19:52:12 +00:00
a5b9bf434f fix(rust): name the servers in a refused restore
All checks were successful
PR Checks / client-build (pull_request) Successful in 27s
PR Checks / server-tests (pull_request) Successful in 34s
PR Checks / frozen-manifest (pull_request) Successful in -1m12s
The walk read "is on rust-oxide"; it now reads the server's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-30 08:45:25 -05:00
7eae4a1e62 feat(rust): NPC profiles and placements pages, the profile leaderboard (runicnpc stage 4)
Admin: Rust NPC profiles (the form RunicNPC reads, per server, shared or
fleet, each server's push state and refusals, replaced profiles with
Restore) and Rust NPC placements (the live map: click to place, pins for
every placement; edit, rename, respawn, remove). The live map takes a pick
handler and pins, unchanged for the public page.

Public: the leaderboard ranks by a profile's kills (D250), and opening a
row shows that player's kills by profile (D252); the killfeed names a
RunicNPC NPC by its own name. Player: your own kills by profile. Titles: a
rule on a profile's kills picks the profile. npcs.test.js covers the
profile checks, adoption, the push, the picker and verb, the triggers, kill
crediting, titles and placements (481 server tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-30 04:42:05 -05:00
fa16f0ad2e feat(rust): NPC profile and placement routes, the event picker, triggers and titles (runicnpc stage 4)
Admin: /admin/rust/npcs for profiles (create, change, delete, restore a
replaced one, push now) and each server's placements (list, add from a map
point, change, remove, rename, respawn). Public: the profiles a leaderboard
ranks by, one profile's ranking counted as the profile says (D247, D250), and
one player's kills by profile (D252). Player: your own kills by profile.

The Place NPCs step offers the site's profiles first, then Rust's own
(D243). rust.npc.died and rust.npc.health are triggers a phase can wait on.
A title rule can rank a profile's kills. Swagger fragment, engagement and
route manifests regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-30 04:34:43 -05:00
564a234890 feat(rust): RunicNPC profiles, their push and adoption, per-profile kills (runicnpc stage 4, WIP)
Schema for site NPC profiles (per server, shared or fleet), the per-server
push record, and kills by profile. The push adopts a server's own profiles
before its first push (D244), keeping one whose name a site profile already
has as replaced (D251). The tally's npcProfileKills are stored per profile
and credited to the site profile pushed under that name (D247).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-30 04:21:46 -05:00
b0143801a2 Merge pull request 'feat(rust): the live map draws monuments by label, minor labels hidden (PLAN_REDESIGNS §4, D196, D213)' (#28) from feat/map-marker-labels into edge
Reviewed-on: #28
2026-09-30 00:17:25 +00:00
4035c523cb fix(rust): the fleet's label list prefers a capitalised spelling
All checks were successful
PR Checks / client-build (pull_request) Successful in 22s
PR Checks / frozen-manifest (pull_request) Successful in 41s
PR Checks / server-tests (pull_request) Successful in 7m45s
Found on the walk: the game spells one label "jungle swamp" on both rigs'
maps, and the fleet list printed it that way beside the minor list's
"Jungle Swamp".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-29 18:19:31 -05:00
b4f71c05cc feat(rust): eight more minor map labels start hidden (D213)
Read from the Carbon rig regenerated at world 6000, seed 981448696, whose map
carries every built-in label: the three that were unverified (Oxum's Gas
Station, Mining Outpost, Ranch) are spelled as written. Adds Canyon B/C,
Lake A, Oasis A/C, Mountain, Train Tunnel Link and Abandoned Cabins, and a
test over that map's 51 real labels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-29 18:12:08 -05:00
0da8f44b55 feat(rust): the live map draws monuments by label, minor labels hidden (PLAN_REDESIGNS §4, D196)
A switch per monument label, a fleet default and a per-server override, on
Admin -> Rust visibility's live map card. Substations, caves, train tunnels,
wells and the other minor labels start hidden; every other label is drawn,
so a monument a game update adds appears. GET /map leaves hidden labels out
of the answer, so the website and the app both lose them.

No schema change: rows are map.marker.<label key> in rust_settings and
rust_map_overrides. No wire change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-29 12:10:47 -05:00
eb184aaac8 Merge pull request 'feat(rust): chat titles rank twenty-three conditions, and admins name the categories (PLAN_REDESIGNS §5, D172-D175, D209)' (#26) from feat/title-conditions into edge
Reviewed-on: #26
2026-09-29 17:00:52 +00:00
837b84580e Merge edge into feat/title-conditions: §3's zone presets
All checks were successful
PR Checks / server-tests (pull_request) Successful in 24s
PR Checks / frozen-manifest (pull_request) Successful in 36s
PR Checks / client-build (pull_request) Successful in 7m39s
Two conflicts, both additive: schema.sql and purge.sql keep both phases'
tables. Swagger fragment (61 paths) and routes.manifest (67 routes)
regenerated against the pinned core; 455 server and 58 client tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-29 11:36:00 -05:00
ea2a40320a Merge pull request 'feat(rust): zone presets, and the zone step's options, messages and dome (PLAN_REDESIGNS §3, D210-D212)' (#27) from feat/zones-domes into edge
Reviewed-on: #27
2026-09-29 16:28:08 +00:00
d89ebbdd23 feat(rust): the zone step labels its domes for what they show (D212)
All checks were successful
PR Checks / client-build (pull_request) Successful in 17s
PR Checks / frozen-manifest (pull_request) Successful in 43s
PR Checks / server-tests (pull_request) Successful in 7m44s
Standard is listed first as the full shaded dome and is the default; each
colour says it shows only where it meets the ground or a building.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-29 09:42:22 -05:00
8361b19c24 feat(rust): zone presets, and the zone step's options, messages and dome (PLAN_REDESIGNS §3, D210)
Admin → Rust zone presets: named sets of ZoneManager flags and settings for
one server, several, or every server (D195), ticked in groups read from each
server's own ZoneManager list in its last hello (D211). A flag not on a
covered server is refused on save with the server named; two presets of one
name may not share a server.

rust.zone.open gains options (one line, NoBuild, radiation=10), enterMessage,
leaveMessage, delivery, dome and domeStack. The options field's dropdown is
rust.options.zone_presets, whose row VALUE is the preset's line, so picking
one copies it into the step (D210) and no published event changes when a
preset does. The line and the dome are checked against the server's hello
on save and in a dry run; bad-option and dome-unavailable are permanent.

Schema: rust_zone_presets, rust_zone_preset_servers. Swagger fragment and
routes.manifest regenerated against the pinned core f0e7d2a.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-29 05:25:44 -05:00