675e879b48a30779075d3c7a9d2ae04b6d5b5b20
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 57419111e6 |
feat(events): UO wave 1 — the verbs that need no protocol change (Phase 9)
module-uo registers its first event actions: `uo.broadcast`, `uo.towncrier.post` and `uo.news.post`, plus the `uo.broadcasts` budget dimension and the three spawn-atlas option sources. The write plane they use has existed since protocol 2.1; what is new is the declaration that lets the event engine drive it unattended. Three things the tree corrected about the plan: - The plan's `on_failure: 'skip'` for `uo.broadcast` is already the default for `risk: 'notify'`, and `on_failure` is what happens AFTER the retries. The lever a module actually has is the failure envelope, so the action answers `retry: false` to everything — and every action declares `budgetMs: 15000`, because core's 10s default deadline fires before `uoLinkClient`'s 12s timeout and `classify()` answers `retry` for a timeout without asking the module. Without the budget the retry refusal is unreachable. - `reconcile()` needs no protocol work. A shard restart wipes both the crier lines and an event's news article, so `perform()` stamps the shard `bootId` into the resource payload and `reconcile()` reports in force exactly the rows whose stamp still matches — correct for the module's own trigger and for core's boot sweep alike. `shardIngest` fires `ctx.events.reconcile()` on a changed `bootId`, after `recordStatus` so the comparison reads the new boot. - Event articles post under `evt-<idempotencyKey>`, because `newsGump.js` uses the bare website post id and re-pushes that set on every reconnect. `ci/core-ref.json` moves to a website `edge` sha for the length of this workstream: `registerEventActions` exists only from MODULE_API 1.10.0, so under the old `main` pin the module does not load at all. Verified locally — the frozen-manifest rig passes against the new pin. Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| c679944181 |
ci(core-ref): pin the core on main, now that the cutover has landed
Module-uo#25 moved this pin onto website `edge` (52eac24) to unbreak frozen-manifest during the engagement window, with its own note saying it reverts to a `main` sha at the cutover. The cutover is step 4 of 7, merged as #26, and website#180 landed the same code on `main` -- so the pin now names a branch that no longer exists. No regeneration, and the reason is checkable rather than asserted: website's tree at 66bb3b9a (main, the cutover merge) and at 52eac24d (the edge head it merged) are the SAME tree, e7a7240. `main` was zero commits ahead, so the merge carried edge's tree unchanged. The frozen-manifest job clones a different commit and reads identical bytes; routes.manifest.json cannot move. What changes is what a reader learns from the file: which core this module was last proved against, named by a ref they can still resolve. Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| 3139cb4364 |
ci(core-ref): pin core at MODULE_API 1.9.0, unbreaking frozen-manifest
The pin was `963d734` -- website `main` at the Teams cutover, MODULE_API **1.6.0**. That core has no `ceilings.js`, no `registerEventTriggers` and no `registerAudiences`, so this module has failed to load into it since Phase 11a added the first of those calls, and `frozen-manifest` has been red on every engagement PR since. The last green run was #39 (`6a276a7`, Phase 10's protocol-5 ingest), which added no `register*` call and so still loaded. The red X was never about the PR in front of it. This is the bump the org lead scheduled for the moment website#178 landed; it should have ridden in Module-uo#24 and did not. New pin: `52eac24` -- website `edge` carrying MODULE_API 1.9.0 (`registerEngagementSeeds`) and the Phase 11b core fixes (website#179). `routes.manifest.json` is unchanged and is NOT regenerated here: this phase's work added triggers, bodies and rules, and not one route. The job's own check confirms it -- 73 routes, all documented. Reproduced locally the way the job does it: core at the new sha, manifest without the module, module installed with `npm ci --omit=dev`, manifest with it, then `frozenManifest.js --check`. The module registers cleanly (26 triggers, 3 audiences) and the check passes. `check:imports` and `check:bundle` clean. Reverts to a `main` sha at the Phase 13 cutover. Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| 3c179e3338 |
fix(release): ship server/commands, and check that the bundle is complete
v1.0.0 installed and then died on every boot:
module "uo" failed to load — {"stage":"register","reason":"Cannot find
module './commands/guild.command'"}
`server/commands/` arrived with the Teams cutover (
|
|||
| fe176920c5 |
ci(core-ref): pin to the Teams cutover, not a phase 3 edge sha
The pin said "edge @ Teams phase 3" and edge is about to stop existing. More to the point, this module has since gained the Team provider, three declared slots, the /guild command and the contribution names on those slots - none of which the pinned core knew about, so the frozen-manifest job has been proving this module against a core older than half of it. routes.manifest.json does not move: the job compares core-with-module against core-without-module, so core's own Teams routes cancel out and what is left is this module's 73, unchanged. Verified locally against the cutover core before moving the pin rather than after. Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| 46e3f5a127 |
ci(core-ref): bump the pin past registerTeamProvider
`frozen-manifest` has been failing since Teams phase 2, on this PR and on #11 before it, for a reason that has nothing to do with either: the pinned core (website#140, the module-system de-UO slice) predates `api.registerTeamProvider`, which this module has called since phase 1 of its Teams work. The module therefore fails to LOAD in the pinned checkout — "api.registerTeamProvider is not a function" — and a module that does not load adds no routes, which the job correctly reports as the module having removed everything it serves. So the red was real and was pointing at the pin, exactly as the pin's own comment says it should: core moves for reasons that have nothing to do with this module, and a bump is a deliberate commit saying which core the module was last proved against. Bumped to `edge` at Teams phase 3 (website#152) — the first core that has both `registerTeamProvider` and the roster projection this module now implements. Reproduced the whole job locally against that core: core's own manifest is current at the new pin, the module loads, and the difference is 73 routes, all documented. `routes.manifest.json` is unchanged and needed no regeneration, which is the expected result for a client-only change. Not bumped to the phase 4 core, deliberately: that is website#153 and is not merged yet. Nothing in this module needs it — the second slot is a client-side declaration, invisible to the route manifest. Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| 5cdcf0fbb6 |
feat(release): ship an OpenAPI fragment, a frozen manifest and a bundle (phase 3, slice 5)
The three artifacts that make this module installable and checkable, closing
phase 3's extraction. Nothing about what the module serves changes: the same 72
URLs, the same behaviour.
**The OpenAPI fragment (MODULE_API.md §2.8, §6.1a) was never built, on either
side.** The 417 `#swagger` annotations came across in slice 1 and went nowhere,
and core's /api/docs.json merged nothing — so every route this module serves was
in no spec at all, which is core's standing rule ("never ship a route that isn't
in the spec") being broken by the extraction rather than by a route.
`server/scripts/swaggerFragment.js` generates it. The prefixes are DERIVED: the
script runs the module's own `register()` against a recording api and asks
`require.cache` which file each router came from, so a mount prefix exists in one
place — `server/index.js` — and not in a table beside it. The 31 schemas moved
here from core's swagger.js, namespaced `Uo…` because core wins every key
collision in the merge; `Error` and `ValidationError` stay referenced by core's
names, since they resolve in the merged document.
**The frozen route manifest (§5.3)** is derived too, and by subtraction: CI
clones core at the ref pinned in ci/core-ref.json, generates its manifest without
this module and then with it, and the difference is what this module serves. That
buys the half of §5.3 that matters most for free — a module that shadowed or
displaced one of core's routes shows up as a REMOVAL, not merely as an addition
elsewhere. The same job checks the fragment against ground truth: every route
must have an operation and every operation must be a route.
**The release workflow** publishes `module-uo-<version>.tar.gz` plus a manifest
carrying its sha256. The version is declared in module.json rather than computed
from commit subjects, and the workflow never writes to a branch — it tags and
publishes — so `main` needs no push exception. The bundle is assembled from an
include list, because an exclude list ships whatever it forgot.
Four annotation defects, inherited from core and never visible until something
generated a spec from these files: two `requestBody` literals a brace short (the
route documented with an empty body), and two descriptions whose inner quoting
swagger-autogen cannot survive — it re-quotes `"` and a backtick to `'` before
evaluating, so either inside a single-quoted description ends the string early
and the annotation is dropped. It reports each one and then prints Success in
green, so the generator now captures its diagnostics and makes them fatal.
Also fixed while writing it: passing one shared `doc` to swagger-autogen six
times. It renders components.schemas from an EXAMPLE object and writes the result
back into what it was handed, so each pass re-wrapped the last and the fragment
came out at 484 MB.
- 409 server tests (+21), 40 client tests unchanged
- swagger-fragment.json: 69 paths covering all 72 routes
- routes.manifest.json: 72 routes; core's own surface unchanged, 0 removals
- verified end to end by assembling the bundle exactly as CI will, unpacking it
into a real core and regenerating the manifest
Refs: docs/website/MODULE_SYSTEM.md §2.7.1, MODULE_API.md §2.8, §5.3, §6.1a
Co-Authored-By: Claude <noreply@anthropic.com>
|