An event action may declare an optional `progress(envelope)`: how its
step stands while the run is live. Core accepts two shapes and
interprets neither:
- a count: { label, left, of }, rendered "Bandits: 3 of 8 left";
- a percentage: { label, percent }, rendered "The Juggernaut: 62%".
How core asks:
- `events/progress.js` asks each step of a live run whose action has
one. It passes the step's own held ledger rows and the reader's
account id, so the module applies its own visibility.
- Each call has a 2 s deadline. A throw, a late answer or any other
shape is a line not shown, never an error on the page.
- One answer per run and reader is cached for 5 s.
- The public event's live occurrence carries the lines as `progress`.
The route takes an optional session for the reader.
- The page renders them under the phase label and re-reads them every
15 s while the event is live.
Core stays game-agnostic: no game's words are in it. Additive, so a
minor bump. Module-uo declares ^1.10.0, registers no action with
progress(), and its actions and pages are unchanged.
From RunicNPC stage 8 (D304, D305).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
688 lines
21 KiB
JSON
688 lines
21 KiB
JSON
{
|
||
"_comment": "Generated event-trigger inventory - the authoritative freeze of CORE's engagement contract (docs/website/ENGAGEMENT.md 4.3). Regenerate with `npm run engagement:manifest` in website/server. A renamed variable, a changed type or a widened ceiling breaks stored templates and rules, so the diff here is the review signal. A module ships its own copy in its bundle; this file never contains one.",
|
||
"moduleApiVersion": "1.12.0",
|
||
"triggers": [
|
||
{
|
||
"id": "event.phase.changed",
|
||
"owner": "core",
|
||
"label": "Event — a new phase",
|
||
"description": "An event that is under way has moved on to its next stage.",
|
||
"kind": "event",
|
||
"subjectKey": "runId",
|
||
"audience": "subscribers",
|
||
"ceiling": "authenticated",
|
||
"version": 2,
|
||
"variables": [
|
||
{
|
||
"name": "runId",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "3692",
|
||
"description": "The run this is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Yew Invasion",
|
||
"description": "The event title."
|
||
},
|
||
{
|
||
"name": "summary",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Orcish warbands are massing north of Yew.",
|
||
"description": "The event’s one-line summary, when it has one."
|
||
},
|
||
{
|
||
"name": "seriesName",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The Yew Campaign",
|
||
"description": "The arc this event belongs to, when it belongs to one."
|
||
},
|
||
{
|
||
"name": "timezone",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "America/New_York",
|
||
"description": "The zone the run was computed in — what a time in the body should be read as."
|
||
},
|
||
{
|
||
"name": "phase",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "assault",
|
||
"description": "The phase key just entered, as authored in the spec."
|
||
},
|
||
{
|
||
"name": "phaseLabel",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The assault",
|
||
"description": "The phase label, when the spec gave it one. Falls back to the key."
|
||
},
|
||
{
|
||
"name": "phaseIndex",
|
||
"type": "int",
|
||
"required": true,
|
||
"example": 2,
|
||
"description": "Which phase this is, counting from 1."
|
||
},
|
||
{
|
||
"name": "phaseCount",
|
||
"type": "int",
|
||
"required": true,
|
||
"example": 4,
|
||
"description": "How many phases the pinned version has in total."
|
||
},
|
||
{
|
||
"name": "eventUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/site/events/the-yew-invasion?run=3692",
|
||
"description": "The public page for this occurrence."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "event.run.cancelled",
|
||
"owner": "core",
|
||
"label": "Event — cancelled",
|
||
"description": "A scheduled event was cancelled by a member of staff.",
|
||
"kind": "event",
|
||
"subjectKey": "runId",
|
||
"audience": "subscribers",
|
||
"ceiling": "authenticated",
|
||
"version": 2,
|
||
"variables": [
|
||
{
|
||
"name": "runId",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "3692",
|
||
"description": "The run this is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Yew Invasion",
|
||
"description": "The event title."
|
||
},
|
||
{
|
||
"name": "summary",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Orcish warbands are massing north of Yew.",
|
||
"description": "The event’s one-line summary, when it has one."
|
||
},
|
||
{
|
||
"name": "seriesName",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The Yew Campaign",
|
||
"description": "The arc this event belongs to, when it belongs to one."
|
||
},
|
||
{
|
||
"name": "timezone",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "America/New_York",
|
||
"description": "The zone the run was computed in — what a time in the body should be read as."
|
||
},
|
||
{
|
||
"name": "reason",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The shard is down for an emergency patch.",
|
||
"description": "What the staff member gave as the reason, when they gave one."
|
||
},
|
||
{
|
||
"name": "eventUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/site/events/the-yew-invasion?run=3692",
|
||
"description": "The public page for this occurrence."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "event.run.completed",
|
||
"owner": "core",
|
||
"label": "Event — finished",
|
||
"description": "An event has finished.",
|
||
"kind": "event",
|
||
"subjectKey": "runId",
|
||
"audience": "subscribers",
|
||
"ceiling": "authenticated",
|
||
"version": 2,
|
||
"variables": [
|
||
{
|
||
"name": "runId",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "3692",
|
||
"description": "The run this is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Yew Invasion",
|
||
"description": "The event title."
|
||
},
|
||
{
|
||
"name": "summary",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Orcish warbands are massing north of Yew.",
|
||
"description": "The event’s one-line summary, when it has one."
|
||
},
|
||
{
|
||
"name": "seriesName",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The Yew Campaign",
|
||
"description": "The arc this event belongs to, when it belongs to one."
|
||
},
|
||
{
|
||
"name": "timezone",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "America/New_York",
|
||
"description": "The zone the run was computed in — what a time in the body should be read as."
|
||
},
|
||
{
|
||
"name": "participantCount",
|
||
"type": "int",
|
||
"required": true,
|
||
"example": 47,
|
||
"description": "How many participants the run recorded. Zero when nothing collected any."
|
||
},
|
||
{
|
||
"name": "durationMinutes",
|
||
"type": "int",
|
||
"required": true,
|
||
"example": 95,
|
||
"description": "How long the run took, start to end, in whole minutes."
|
||
},
|
||
{
|
||
"name": "eventUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/site/events/the-yew-invasion?run=3692",
|
||
"description": "The public page for this occurrence."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "event.run.ending",
|
||
"owner": "core",
|
||
"label": "Event — winding down",
|
||
"description": "An event is drawing to a close.",
|
||
"kind": "event",
|
||
"subjectKey": "runId",
|
||
"audience": "subscribers",
|
||
"ceiling": "authenticated",
|
||
"version": 2,
|
||
"variables": [
|
||
{
|
||
"name": "runId",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "3692",
|
||
"description": "The run this is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Yew Invasion",
|
||
"description": "The event title."
|
||
},
|
||
{
|
||
"name": "summary",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Orcish warbands are massing north of Yew.",
|
||
"description": "The event’s one-line summary, when it has one."
|
||
},
|
||
{
|
||
"name": "seriesName",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The Yew Campaign",
|
||
"description": "The arc this event belongs to, when it belongs to one."
|
||
},
|
||
{
|
||
"name": "timezone",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "America/New_York",
|
||
"description": "The zone the run was computed in — what a time in the body should be read as."
|
||
},
|
||
{
|
||
"name": "eventUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/site/events/the-yew-invasion?run=3692",
|
||
"description": "The public page for this occurrence."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "event.run.failed",
|
||
"owner": "core",
|
||
"label": "Event — run failed",
|
||
"description": "An event stopped before it finished.",
|
||
"kind": "event",
|
||
"subjectKey": "runId",
|
||
"audience": "admin",
|
||
"ceiling": "admin",
|
||
"version": 1,
|
||
"variables": [
|
||
{
|
||
"name": "runId",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "3692",
|
||
"description": "The run this is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Yew Invasion",
|
||
"description": "The event title."
|
||
},
|
||
{
|
||
"name": "summary",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Orcish warbands are massing north of Yew.",
|
||
"description": "The event’s one-line summary, when it has one."
|
||
},
|
||
{
|
||
"name": "seriesName",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The Yew Campaign",
|
||
"description": "The arc this event belongs to, when it belongs to one."
|
||
},
|
||
{
|
||
"name": "timezone",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "America/New_York",
|
||
"description": "The zone the run was computed in — what a time in the body should be read as."
|
||
},
|
||
{
|
||
"name": "phase",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "assault",
|
||
"description": "The phase it failed in, when it had entered one."
|
||
},
|
||
{
|
||
"name": "error",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "sidecar responded 503",
|
||
"description": "The run’s last error, verbatim from the run row."
|
||
},
|
||
{
|
||
"name": "runUrl",
|
||
"type": "url",
|
||
"required": true,
|
||
"example": "/admin/events/runs/3692",
|
||
"description": "Site-relative path to the run console."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "event.run.scheduled",
|
||
"owner": "core",
|
||
"label": "Event — scheduled",
|
||
"description": "A new event has been added to the calendar.",
|
||
"kind": "event",
|
||
"subjectKey": "runId",
|
||
"audience": "subscribers",
|
||
"ceiling": "authenticated",
|
||
"version": 2,
|
||
"variables": [
|
||
{
|
||
"name": "runId",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "3692",
|
||
"description": "The run this is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Yew Invasion",
|
||
"description": "The event title."
|
||
},
|
||
{
|
||
"name": "summary",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Orcish warbands are massing north of Yew.",
|
||
"description": "The event’s one-line summary, when it has one."
|
||
},
|
||
{
|
||
"name": "seriesName",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The Yew Campaign",
|
||
"description": "The arc this event belongs to, when it belongs to one."
|
||
},
|
||
{
|
||
"name": "timezone",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "America/New_York",
|
||
"description": "The zone the run was computed in — what a time in the body should be read as."
|
||
},
|
||
{
|
||
"name": "startsAt",
|
||
"type": "datetime",
|
||
"required": true,
|
||
"example": "2026-09-12T20:00:00.000Z",
|
||
"description": "When the occurrence is due to start, UTC."
|
||
},
|
||
{
|
||
"name": "startsAtLabel",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Saturday 12 September at 8:00 pm (America/New_York)",
|
||
"description": "The start time written out in the shard-local zone, for a mail to read."
|
||
},
|
||
{
|
||
"name": "eventUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/site/events/the-yew-invasion?run=3692",
|
||
"description": "The public page for this occurrence."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "event.run.started",
|
||
"owner": "core",
|
||
"label": "Event — starting now",
|
||
"description": "A scheduled event has begun.",
|
||
"kind": "event",
|
||
"subjectKey": "runId",
|
||
"audience": "subscribers",
|
||
"ceiling": "authenticated",
|
||
"version": 2,
|
||
"variables": [
|
||
{
|
||
"name": "runId",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "3692",
|
||
"description": "The run this is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Yew Invasion",
|
||
"description": "The event title."
|
||
},
|
||
{
|
||
"name": "summary",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Orcish warbands are massing north of Yew.",
|
||
"description": "The event’s one-line summary, when it has one."
|
||
},
|
||
{
|
||
"name": "seriesName",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "The Yew Campaign",
|
||
"description": "The arc this event belongs to, when it belongs to one."
|
||
},
|
||
{
|
||
"name": "timezone",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "America/New_York",
|
||
"description": "The zone the run was computed in — what a time in the body should be read as."
|
||
},
|
||
{
|
||
"name": "startsAt",
|
||
"type": "datetime",
|
||
"required": true,
|
||
"example": "2026-09-12T20:00:00.000Z",
|
||
"description": "When it actually started, UTC."
|
||
},
|
||
{
|
||
"name": "startsAtLabel",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Saturday 12 September at 8:00 pm (America/New_York)",
|
||
"description": "The start time written out in the shard-local zone, for a mail to read."
|
||
},
|
||
{
|
||
"name": "eventUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/site/events/the-yew-invasion?run=3692",
|
||
"description": "The public page for this occurrence."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "news.post",
|
||
"owner": "core",
|
||
"label": "News post published",
|
||
"description": "A news / Five-on-Friday / newsletter post was published.",
|
||
"kind": "event",
|
||
"subjectKey": null,
|
||
"audience": "subscribers",
|
||
"ceiling": "authenticated",
|
||
"version": 1,
|
||
"variables": [
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "Five on Friday — the Yew invasion",
|
||
"description": "The post title."
|
||
},
|
||
{
|
||
"name": "excerpt",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Four new champion spawns, and the fate of the Yew moongate…",
|
||
"description": "A plain-text summary, already stripped of markup."
|
||
},
|
||
{
|
||
"name": "category",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Five on Friday",
|
||
"description": "The post category, when it has one."
|
||
},
|
||
{
|
||
"name": "postUrl",
|
||
"type": "url",
|
||
"required": true,
|
||
"example": "/site/news",
|
||
"description": "Site-relative path to the post. The news list today — the site has no per-post route."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "team.announcement",
|
||
"owner": "core",
|
||
"label": "Team — announcement",
|
||
"description": "A leader posted an announcement in a Team.",
|
||
"kind": "event",
|
||
"subjectKey": "teamName",
|
||
"audience": "members",
|
||
"ceiling": "members",
|
||
"version": 1,
|
||
"variables": [
|
||
{
|
||
"name": "teamName",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Silver Anvil",
|
||
"description": "The Team the event is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "authorName",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "Marisol",
|
||
"description": "Display name of the leader who posted."
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "Siege practice moved to Sunday",
|
||
"description": "The announcement title."
|
||
},
|
||
{
|
||
"name": "excerpt",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "We are moving practice to Sunday 8pm…",
|
||
"description": "Plain-text excerpt of the announcement body."
|
||
},
|
||
{
|
||
"name": "postUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/guilds/the-silver-anvil/forum/419",
|
||
"description": "Site-relative path to the announcement."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "team.forum.post",
|
||
"owner": "core",
|
||
"label": "Team — new forum post",
|
||
"description": "A new thread or reply in a Team forum.",
|
||
"kind": "event",
|
||
"subjectKey": "teamName",
|
||
"audience": "members",
|
||
"ceiling": "members",
|
||
"version": 1,
|
||
"variables": [
|
||
{
|
||
"name": "teamName",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Silver Anvil",
|
||
"description": "The Team the event is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "authorName",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "Darrow",
|
||
"description": "Display name of the poster."
|
||
},
|
||
{
|
||
"name": "threadTitle",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "Tuesday champ rotation",
|
||
"description": "Title of the thread the post belongs to."
|
||
},
|
||
{
|
||
"name": "excerpt",
|
||
"type": "string",
|
||
"required": false,
|
||
"example": "Moving the Tuesday run an hour later…",
|
||
"description": "Plain-text excerpt of the post body, already stripped of markup."
|
||
},
|
||
{
|
||
"name": "postUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/guilds/the-silver-anvil/forum/412",
|
||
"description": "Site-relative path to the post."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "team.leadership.changed",
|
||
"owner": "core",
|
||
"label": "Team — leadership change",
|
||
"description": "Leadership changed in a Team.",
|
||
"kind": "event",
|
||
"subjectKey": "teamName",
|
||
"audience": "members",
|
||
"ceiling": "members",
|
||
"version": 1,
|
||
"variables": [
|
||
{
|
||
"name": "teamName",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Silver Anvil",
|
||
"description": "The Team the event is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "leaderName",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "Marisol",
|
||
"description": "Display name of the new leader."
|
||
},
|
||
{
|
||
"name": "teamUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/guilds/the-silver-anvil",
|
||
"description": "Site-relative path to the Team page."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "team.member.joined",
|
||
"owner": "core",
|
||
"label": "Team — new member",
|
||
"description": "Someone joined a Team.",
|
||
"kind": "event",
|
||
"subjectKey": "teamName",
|
||
"audience": "members",
|
||
"ceiling": "members",
|
||
"version": 1,
|
||
"variables": [
|
||
{
|
||
"name": "teamName",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "The Silver Anvil",
|
||
"description": "The Team the event is about. Also the cooldown subject."
|
||
},
|
||
{
|
||
"name": "memberName",
|
||
"type": "string",
|
||
"required": true,
|
||
"example": "Darrow",
|
||
"description": "Display name of the member who joined."
|
||
},
|
||
{
|
||
"name": "teamUrl",
|
||
"type": "url",
|
||
"required": false,
|
||
"example": "/guilds/the-silver-anvil",
|
||
"description": "Site-relative path to the Team page. Absent when no module supplies a pageUrlTemplate."
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|