@bongos/core 1.20.79 → 1.20.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.bongos-core.json +104 -49
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +8 -0
  4. package/clients/bongos-client/index.cjs +8 -0
  5. package/clients/bongos-client/index.d.ts +13 -0
  6. package/clients/bongos-client/index.mjs +8 -0
  7. package/docs/adr/0161-publish-on-merge.md +1 -1
  8. package/docs/adr/0361-merges-publish-as-candidates-release-decides-what-others-are-offered.md +59 -0
  9. package/docs/adr/README.md +1 -0
  10. package/docs/api/openapi.json +258 -4
  11. package/docs/api-reference.md +7 -3
  12. package/docs/copy-inventory.md +59 -53
  13. package/docs/copy-registry.json +120 -66
  14. package/docs/module-api-changelog.md +4 -0
  15. package/docs/page-inventory.json +2 -1
  16. package/docs/page-readings.json +86 -81
  17. package/docs/recipes/private-npm-distribution.md +2 -0
  18. package/docs/recipes/upgrading-the-core.md +1 -1
  19. package/modules/autonomy/cadence.js +3 -0
  20. package/modules/autonomy/db.js +136 -0
  21. package/modules/autonomy/fence.js +88 -3
  22. package/modules/autonomy/migrations/autonomy_005_builder_scope.sql +55 -0
  23. package/modules/autonomy/routes/autonomy.js +123 -3
  24. package/modules/government/catalog.js +9 -1
  25. package/modules/government/migrations/government_022_autonomy_run.sql +38 -0
  26. package/modules/hall-ui/public/gate.html +5 -2
  27. package/modules/hall-ui/public/gate.js +73 -4
  28. package/modules/hall-ui/public/settings-autobongos.js +156 -0
  29. package/modules/hall-ui/public/settings.html +19 -0
  30. package/modules/hall-ui/public/settings.js +1 -0
  31. package/modules/lifecycle/module.json +2 -1
  32. package/modules/lifecycle/routes/lifecycle.js +7 -0
  33. package/modules/lifecycle/workflow-dispatch.js +45 -0
  34. package/modules/npm-release/module.json +2 -1
  35. package/modules/npm-release/public/work.js +74 -0
  36. package/modules/npm-release/release.js +129 -0
  37. package/modules/npm-release/routes/release.js +65 -0
  38. package/modules/npm-release/work.js +16 -0
  39. package/package-lock.json +2 -2
  40. package/package.json +1 -1
  41. package/release-notes.json +16 -0
  42. package/scripts/gds/provision-core-upgrade.js +30 -2
  43. package/scripts/gds/release-core.js +80 -0
  44. package/scripts/gds/update-channel.js +12 -3
  45. package/src/bongos/core-update.js +17 -8
  46. package/src/module-api.js +1 -1
  47. package/tests/autonomy_builder_scope.mjs +474 -0
  48. package/tests/autonomy_fence_priority.mjs +3 -1
  49. package/tests/core_update_banner.mjs +41 -5
  50. package/tests/core_upgrade_runner.mjs +66 -1
  51. package/tests/npm_release_release.mjs +195 -0
  52. package/tests/release_core.mjs +110 -0
  53. package/tests/update_channel.mjs +7 -0
@@ -1,6 +1,6 @@
1
1
  # 0161 — Publish on merge: every merge to core `main` auto-publishes `@bongos/core`
2
2
 
3
- - **Status:** Accepted
3
+ - **Status:** Accepted. **Amended by [ADR 0361](0361-merges-publish-as-candidates-release-decides-what-others-are-offered.md)** (task 1004298): merges publish as candidates under `next`; `latest` moves only on Release.
4
4
  - **Date:** 2026-08-08
5
5
  - **Deciders:** the owner (Archon), Claude. The owner chose this directly after reviewing the pipeline end-to-end: "any merge can publish, we can add in more complexity later."
6
6
  - **Task:** task 1002620 (BONGOS-V1, goal 1000024 — build-pipeline integrity)
@@ -0,0 +1,59 @@
1
+ # ADR 0361 — Merges publish as candidates; Release on /deploy decides what other projects are offered
2
+
3
+ - **Status:** Accepted. Ships **inert**: candidates start only when the owner sets `PUBLISH_AS_CANDIDATE=1` (see *Arming*).
4
+ - **Date:** 2026-10-01
5
+ - **Task:** [task 1004298](https://cloudbongos.com/builders#/task/1004298) (goal 1000090 — BONGOS-V2), split out of [task 1002622](https://cloudbongos.com/builders#/task/1002622) §3.
6
+ - **Deciders:** the owner. Decisions of 2026-09-25/26: nothing reaches other projects until it is released, **patches included**; the button belongs to the `npm-release` module.
7
+ - **Amends:** [ADR 0161](0161-publish-on-merge.md) (publish on merge). Every merge still publishes; it no longer becomes what every project is offered.
8
+ - **Builds on:** [ADR 0360](0360-bongos-follows-every-candidate-every-other-project-follows-releases.md) (the per-instance follow), [ADR 0136](0136-update-channel-subscription-policy.md) (channels).
9
+
10
+ ## Context
11
+
12
+ Under ADR 0161 every merge to core `main` publishes a new `@bongos/core` under npm's `latest` label, and every consumer read "newest on npm" as "what you may move to". So a merge was a release to every project, minutes after it landed, with no point at which the owner said yes.
13
+
14
+ ADR 0360 gave each instance a **follow**: `released` (at or below `latest`) or `candidates` (every version). Until now the two picked the same target, because `latest` was always the newest version.
15
+
16
+ ## Decision
17
+
18
+ ### D1 — Merges publish under `next`
19
+
20
+ `publish.yml` publishes with `--tag next` when the repository variable `PUBLISH_AS_CANDIDATE=1`. The version is on npm, installable by exact number, and `latest` does not move. Unset, the lane publishes under `latest` exactly as before. That is what lets this change land without changing anything.
21
+
22
+ ### D2 — Release moves `latest`, in GitHub
23
+
24
+ Release is a second job in `publish.yml` (`release`, on `workflow_dispatch` with `release_version`). It asks `scripts/gds/release-core.js` whether the version may be released, then runs `npm dist-tag add @bongos/core@<v> latest`.
25
+
26
+ - **The version must be published, stable, and newer than the current release.** An older version would move every project's offer backwards. That is a rollback for everyone, and it stays a terminal act. Releasing the current release again is a no-op.
27
+ - **It lives in `publish.yml`, not a new file.** npm's trusted publisher for `@bongos/core` names `publish.yml`. Since 2026-09-30 the same OIDC identity can move dist-tags once "Allow npm dist-tag" is ticked on that entry. A separate file would need a second trusted-publisher entry or a long-lived token, and this lane was built to be rid of the token (task 1003202).
28
+ - **The version reaches the shell through `env`**, never `${{ }}` inside a script, and is refused unless it is `x.y.z`.
29
+
30
+ ### D3 — The button starts the job; the server never holds an npm credential
31
+
32
+ `POST /api/bongos/npm-release/release` (`core.pin.move`, the deploy page's own atom) dispatches the release job through GitHub's API. The GitHub credential is the server's existing GitHub App; the call reaches it through a one-function port, `lifecycle.workflowDispatch`. The `npm-release` module can start a workflow and do nothing else with that credential. The route applies `releaseDecision` first, the same function the job applies again. So the button cannot promise what the job would refuse, and the job remains the gate.
33
+
34
+ ### D4 — The button shows the evidence
35
+
36
+ The deploy page's **Release** section lists the versions this hall runs that are not released, newest first. Each shows how long it has run on this hall and whether a move to it was ever rolled back here, from the `core_upgrades` ledger. Release covers a whole version: everything merged up to it.
37
+
38
+ ### D5 — Every consumer offers only what is released
39
+
40
+ - The update sweep (ADR 0360) already follows `released` by default.
41
+ - The "update available" banner (`src/bongos/core-update.js`) offers versions at or below `latest`, read from the same packument. With no readable label it has no answer.
42
+ - The platform's upgrade runner for hosted projects (`scripts/gds/provision-core-upgrade.js`) offers a project the versions its follow admits. The follow comes from its hosting shape: the `control-plane` row is the platform hall and takes candidates; every other shape takes releases (`followForShape`). It is derived, not a column, because there is exactly one platform hall. A column someone could set on a tenant would be one more way to hand a project an unreleased version.
43
+
44
+ ## Arming (owner steps, in this order)
45
+
46
+ 1. **Platform hall follows candidates.** On the control plane, set the platform's entry in `config/update-subscriptions.json` to `"follow": "candidates"` (ADR 0360). Otherwise, once D1 is on, cloudbongos.com stops updating itself.
47
+ 2. **npm:** on npmjs.com → `@bongos/core` → Settings → Trusted publishing, tick **Allow npm dist-tag** on the `publish.yml` entry.
48
+ 3. **GitHub App:** give the server's GitHub App **Actions: Read and write** on this repository, and accept the permission change on the installation.
49
+ 4. **Switch on:** set the repository Actions variable `PUBLISH_AS_CANDIDATE=1`.
50
+
51
+ Until step 4, every version this hall runs is already `latest`, so the Release section reads "Nothing is waiting" and nothing else changes. A press made before steps 2–3 fails with the reason (no dist-tag permission, or the App lacks Actions: write) and moves nothing.
52
+
53
+ ## Consequences
54
+
55
+ - Other projects stop receiving merges the moment step 4 is done. They receive the next version the owner releases, and everything merged before it.
56
+ - The deploy page's "Running here, not released" stage fills between merges and a Release, and empties after one.
57
+ - A version can be released only after this hall has run it, because the candidate list stops at the live version. The evidence is real, not inferred.
58
+ - **Rejected:** a long-lived npm token in a separate release workflow (the risk task 1003202 removed). Choosing "released" by a git tag or a file in the repo (every instance already reads npm, and a second source of truth would drift). A per-instance follow column (D5).
59
+ - **Proof:** `tests/release_core.mjs` (the rule and the workflow wiring), `tests/npm_release_release.mjs` (evidence, the press, the GitHub call, the route gate), `tests/core_update_banner.mjs` (only released versions offered), `tests/core_upgrade_runner.mjs` (the platform hall takes a candidate; a tenant is refused one), `tests/update_channel.mjs` (`followForShape`).
@@ -479,3 +479,4 @@ These 20 numbers are each shared by exactly two files. They are **accepted histo
479
479
  | 0358 | [**A hall wears a look, and its night takes a tint of it** ([task 1004421](https://cloudbongos.com/builders#/task/1004421), goal 1000121 — BV2.PS06; owner D2 + D8, 2026-09-30). Amends [ADR 0219](0219-a-look-is-a-branding-pack-the-style-library.md) (a look could not carry a dark ground) and DESIGN.md's pure-black rule, for halls only. **D1:** the night tint is a formula over the thirteen — the four dark grounds take 5–6% of the look's accent (src/night-tint.js), emitted after the sheet as both dark twins; no token added. **D2:** on by default, and only a chosen look turns it on — a hall with no look is unchanged. **D3:** the apex and hub stay pure black (ADR 0204). **D4:** a custom look is ONE accent for both modes, its lightness nudged until every pair the hall paints with it reads (lookAdjustAccent, client copy test-pinned). **D5:** look + night_tint join the provisioning settings vocabulary; the accent and logo address ride as companion env; the instance resolves the look from the style library. **D6:** a logo is PNG/JPEG/WebP ≤256 KB, magic-sniffed, never SVG, served content-addressed; it is the hall mark and the favicon. Rejected: per-look dark palettes, two custom accents, refusing an unreadable accent, sending the palette over env.](0358-a-hall-wears-a-look-and-its-night-takes-a-tint.md) | hall / branding / design world |
480
480
  | 0359 | [**Nobody sets a module's score by hand; a Metic+ person can ask for a re-check** ([task 1003796](https://cloudbongos.com/builders#/task/1003796) · goal 1000091, criterion `wa5-quality-assessed`). Amends [ADR 0343](0343-a-module-score-is-a-security-gate-then-an-average-of-visible-parts.md) D6 and [ADR 0347](0347-every-store-module-ships-a-how-to.md) D5 on the owner's ruling: there is no score override. A score only ever comes from its signals. Instead `POST /store/modules/:key/versions/:version/reassess { reason }`, gated by the new `module.assessment.rerun` atom (metic floor, granted to metic + archon by `government_021`), queues the same assessment a publish runs. A reason is required and nothing else is accepted. The delist (task 1003797) is unchanged.](0359-nobody-sets-a-module-score-by-hand-metic-can-ask-for-a-re-check.md) | module store / assessment / permissions |
481
481
  | 0360 | [**Bongos follows every candidate; every other project follows releases** ([task 1004297](https://cloudbongos.com/builders#/task/1004297), goal 1000090 — the owner's 2026-09-26 decision that the Bongos hall takes every candidate automatically). Amends ADR 0136. **D1:** a per-instance `follow` beside the channel — `released` (default: at or below the registry's `latest` label) or `candidates` (every version, the platform hall only). **D2:** released is the `latest` dist-tag, read separately; an unreadable label skips the instance, never a guess. **D3:** the timer period is the lag — 15 min declared, installed by task 1003969. **D4:** a version that failed here is held for a day per instance (recorded in the sweep's config home), while any newer version is taken at once — no restart loop at a 15-minute cadence. **D5:** the deploy page's "Upgrades on this hall" — the core_upgrades ledger, rollbacks flagged, and a published version waiting past 30 min said to be the automation stopping. Rejected: a second runner, CI pushing to the box, a hold only a human clears.](0360-bongos-follows-every-candidate-every-other-project-follows-releases.md) | update channel / deploy / core update |
482
+ | 0361 | [**Merges publish as candidates; Release on /deploy decides what other projects are offered** ([task 1004298](https://cloudbongos.com/builders#/task/1004298), goal 1000090). Amends ADR 0161. **D1:** merges publish under `next` when `PUBLISH_AS_CANDIDATE=1` (ships inert). **D2:** a `release` job in publish.yml moves `latest` (release-core.js: published, stable, newer than the release) over the same OIDC trusted publisher — no npm token. **D3:** /deploy's Release button (`core.pin.move`) dispatches it through the one-function `lifecycle.workflowDispatch` port. **D4:** evidence beside each button — hours on this hall, ever rolled back. **D5:** the banner and the hosted-project runner offer only released versions; the control-plane row follows candidates. Arming: roster follow → npm dist-tag permission → App Actions: write → the variable.](0361-merges-publish-as-candidates-release-decides-what-others-are-offered.md) | publish / release / update channel |
@@ -1728,6 +1728,65 @@
1728
1728
  "security": []
1729
1729
  }
1730
1730
  },
1731
+ "/autonomy/builders/{builderId}/pause": {
1732
+ "post": {
1733
+ "operationId": "post_autonomy_builders_builderId_pause",
1734
+ "tags": [
1735
+ "autonomy"
1736
+ ],
1737
+ "summary": "POST /autonomy/builders/:builderId/pause",
1738
+ "description": "The owner pauses or resumes ONE builder's runner without throwing the master switch. Same atom as the kill switch: stopping a machine is the same act whether it is everyone's or one person's, and the paused builder must not be able to lift it (autonomy.run does not reach this route).\n\n**Rank:** `archon` — Archon only (rank and identity management + the escalation keys — the trust boundary).\n\n**Permissions:** `autonomy.fence.manage` (all required).",
1739
+ "x-rank": "archon",
1740
+ "x-source": "modules/autonomy/routes/autonomy.js",
1741
+ "x-permissions": [
1742
+ "autonomy.fence.manage"
1743
+ ],
1744
+ "parameters": [
1745
+ {
1746
+ "name": "builderId",
1747
+ "in": "path",
1748
+ "required": true,
1749
+ "schema": {
1750
+ "type": "string"
1751
+ },
1752
+ "description": "Path parameter `builderId`."
1753
+ }
1754
+ ],
1755
+ "requestBody": {
1756
+ "required": true,
1757
+ "content": {
1758
+ "application/json": {
1759
+ "schema": {
1760
+ "$ref": "#/components/schemas/PostAutonomyBuildersBuilderIdPauseRequest"
1761
+ }
1762
+ }
1763
+ },
1764
+ "x-validated": true
1765
+ },
1766
+ "responses": {
1767
+ "200": {
1768
+ "description": "Success."
1769
+ },
1770
+ "400": {
1771
+ "$ref": "#/components/responses/ValidationFailed"
1772
+ },
1773
+ "401": {
1774
+ "$ref": "#/components/responses/Unauthorized"
1775
+ },
1776
+ "403": {
1777
+ "$ref": "#/components/responses/Forbidden"
1778
+ },
1779
+ "404": {
1780
+ "$ref": "#/components/responses/NotFound"
1781
+ }
1782
+ },
1783
+ "security": [
1784
+ {
1785
+ "builderSession": []
1786
+ }
1787
+ ]
1788
+ }
1789
+ },
1731
1790
  "/autonomy/fence": {
1732
1791
  "get": {
1733
1792
  "operationId": "get_autonomy_fence",
@@ -1735,7 +1794,7 @@
1735
1794
  "autonomy"
1736
1795
  ],
1737
1796
  "summary": "GET /autonomy/fence",
1738
- "description": "The runner's own read, every iteration. ANY-BUILDER on purpose: learning that you must stop should never require an elevated session, because the failure mode of \"could not read the fence\" is a machine that keeps going. The body carries no secret — it is a boolean, a reason string and a list of goal ids.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
1797
+ "description": "The runner's own read, every iteration. ANY-BUILDER on purpose: learning that you must stop should never require an elevated session, because the failure mode of \"could not read the fence\" is a machine that keeps going. The body carries no secret — it is a boolean, a reason string and a list of goal ids. THE CALLER'S fence, not the project's (task 1004501). The top-level `enabled` and `goals` are what THIS builder's runner may do: the project switch, then `autonomy.run`, then the owner's pause on this builder, and the allowlist narrowed to their own picks (fence.js effectiveFence). Computing it here keeps the runner dumb and means a runner that predates this change is narrowed too. The unnarrowed project fence rides along as `project` for the owner's page.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
1739
1798
  "x-rank": "any-builder",
1740
1799
  "x-source": "modules/autonomy/routes/autonomy.js",
1741
1800
  "responses": {
@@ -1996,6 +2055,58 @@
1996
2055
  ]
1997
2056
  }
1998
2057
  },
2058
+ "/autonomy/me/goals": {
2059
+ "put": {
2060
+ "operationId": "put_autonomy_me_goals",
2061
+ "tags": [
2062
+ "autonomy"
2063
+ ],
2064
+ "summary": "PUT /autonomy/me/goals",
2065
+ "description": "A builder picks which allowlisted goals THEIR runner works. Replaces the whole list; `[]` means \"my runner takes no work\". Keyed by the session, never the body, so nobody can set another builder's picks. Behind `autonomy.run`: a builder who may not run a runner has nothing to scope. A goal not on the project allowlist is refused with 409 and nothing is written — the pick can narrow the project fence and never widen it.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `autonomy.run` (all required).",
2066
+ "x-rank": "metic+archon",
2067
+ "x-source": "modules/autonomy/routes/autonomy.js",
2068
+ "x-permissions": [
2069
+ "autonomy.run"
2070
+ ],
2071
+ "requestBody": {
2072
+ "required": true,
2073
+ "content": {
2074
+ "application/json": {
2075
+ "schema": {
2076
+ "$ref": "#/components/schemas/PutAutonomyMeGoalsRequest"
2077
+ }
2078
+ }
2079
+ },
2080
+ "x-validated": true
2081
+ },
2082
+ "responses": {
2083
+ "200": {
2084
+ "description": "Success.",
2085
+ "content": {
2086
+ "application/json": {
2087
+ "schema": {
2088
+ "$ref": "#/components/schemas/PutAutonomyMeGoalsResponse"
2089
+ }
2090
+ }
2091
+ }
2092
+ },
2093
+ "400": {
2094
+ "$ref": "#/components/responses/ValidationFailed"
2095
+ },
2096
+ "401": {
2097
+ "$ref": "#/components/responses/Unauthorized"
2098
+ },
2099
+ "403": {
2100
+ "$ref": "#/components/responses/Forbidden"
2101
+ }
2102
+ },
2103
+ "security": [
2104
+ {
2105
+ "builderSession": []
2106
+ }
2107
+ ]
2108
+ }
2109
+ },
1999
2110
  "/autonomy/precheck": {
2000
2111
  "get": {
2001
2112
  "operationId": "get_autonomy_precheck",
@@ -2068,6 +2179,47 @@
2068
2179
  ]
2069
2180
  }
2070
2181
  },
2182
+ "/autonomy/runners/all": {
2183
+ "get": {
2184
+ "operationId": "get_autonomy_runners_all",
2185
+ "tags": [
2186
+ "autonomy"
2187
+ ],
2188
+ "summary": "GET /autonomy/runners/all",
2189
+ "description": "The owner's view of every builder's runners: who, which goals they picked, whether they are paused, and each runner's health — the server's verdict, as GET /autonomy/runners attaches it. Owner-only: a heartbeat names a machine and its hostname, which is each builder's own business (task 1003905), and the owner is the one person who needs every row to run the fence.\n\n**Rank:** `archon` — Archon only (rank and identity management + the escalation keys — the trust boundary).\n\n**Permissions:** `autonomy.fence.manage` (all required).",
2190
+ "x-rank": "archon",
2191
+ "x-source": "modules/autonomy/routes/autonomy.js",
2192
+ "x-permissions": [
2193
+ "autonomy.fence.manage"
2194
+ ],
2195
+ "responses": {
2196
+ "200": {
2197
+ "description": "Success.",
2198
+ "content": {
2199
+ "application/json": {
2200
+ "schema": {
2201
+ "$ref": "#/components/schemas/GetAutonomyRunnersAllResponse"
2202
+ }
2203
+ }
2204
+ }
2205
+ },
2206
+ "400": {
2207
+ "$ref": "#/components/responses/BadRequest"
2208
+ },
2209
+ "401": {
2210
+ "$ref": "#/components/responses/Unauthorized"
2211
+ },
2212
+ "403": {
2213
+ "$ref": "#/components/responses/Forbidden"
2214
+ }
2215
+ },
2216
+ "security": [
2217
+ {
2218
+ "builderSession": []
2219
+ }
2220
+ ]
2221
+ }
2222
+ },
2071
2223
  "/autonomy/runs": {
2072
2224
  "get": {
2073
2225
  "operationId": "get_autonomy_runs",
@@ -14113,6 +14265,51 @@
14113
14265
  ]
14114
14266
  }
14115
14267
  },
14268
+ "/npm-release/release": {
14269
+ "post": {
14270
+ "operationId": "post_npm_release_release",
14271
+ "tags": [
14272
+ "npm-release"
14273
+ ],
14274
+ "summary": "POST /npm-release/release",
14275
+ "description": "**Rank:** `archon` — Archon only (rank and identity management + the escalation keys — the trust boundary).\n\n**Permissions:** `core.pin.move` (all required).",
14276
+ "x-rank": "archon",
14277
+ "x-source": "modules/npm-release/routes/release.js",
14278
+ "x-permissions": [
14279
+ "core.pin.move"
14280
+ ],
14281
+ "requestBody": {
14282
+ "required": true,
14283
+ "content": {
14284
+ "application/json": {
14285
+ "schema": {
14286
+ "$ref": "#/components/schemas/PostNpmReleaseReleaseRequest"
14287
+ }
14288
+ }
14289
+ },
14290
+ "x-validated": true
14291
+ },
14292
+ "responses": {
14293
+ "200": {
14294
+ "description": "Success."
14295
+ },
14296
+ "400": {
14297
+ "$ref": "#/components/responses/ValidationFailed"
14298
+ },
14299
+ "401": {
14300
+ "$ref": "#/components/responses/Unauthorized"
14301
+ },
14302
+ "403": {
14303
+ "$ref": "#/components/responses/Forbidden"
14304
+ }
14305
+ },
14306
+ "security": [
14307
+ {
14308
+ "builderSession": []
14309
+ }
14310
+ ]
14311
+ }
14312
+ },
14116
14313
  "/npm-release/task/{id}": {
14117
14314
  "get": {
14118
14315
  "operationId": "get_npm_release_task_id",
@@ -23317,6 +23514,15 @@
23317
23514
  "admitted"
23318
23515
  ]
23319
23516
  },
23517
+ "GetAutonomyRunnersAllResponse": {
23518
+ "type": "object",
23519
+ "properties": {
23520
+ "builders": {}
23521
+ },
23522
+ "required": [
23523
+ "builders"
23524
+ ]
23525
+ },
23320
23526
  "GetAutonomyRunnersResponse": {
23321
23527
  "type": "object",
23322
23528
  "properties": {
@@ -26346,6 +26552,22 @@
26346
26552
  "revoked"
26347
26553
  ]
26348
26554
  },
26555
+ "PostAutonomyBuildersBuilderIdPauseRequest": {
26556
+ "type": "object",
26557
+ "properties": {
26558
+ "paused": {
26559
+ "type": "boolean"
26560
+ },
26561
+ "reason": {
26562
+ "type": "string",
26563
+ "maxLength": 500
26564
+ }
26565
+ },
26566
+ "required": [
26567
+ "paused"
26568
+ ],
26569
+ "additionalProperties": false
26570
+ },
26349
26571
  "PostAutonomyFenceGoalsRequest": {
26350
26572
  "type": "object",
26351
26573
  "properties": {
@@ -28893,6 +29115,19 @@
28893
29115
  ],
28894
29116
  "additionalProperties": false
28895
29117
  },
29118
+ "PostNpmReleaseReleaseRequest": {
29119
+ "type": "object",
29120
+ "properties": {
29121
+ "version": {
29122
+ "type": "string",
29123
+ "maxLength": 32
29124
+ }
29125
+ },
29126
+ "required": [
29127
+ "version"
29128
+ ],
29129
+ "additionalProperties": false
29130
+ },
28896
29131
  "PostOverrideRequestsIdDecideRequest": {
28897
29132
  "type": "object",
28898
29133
  "properties": {
@@ -30957,6 +31192,25 @@
30957
31192
  "criteria"
30958
31193
  ]
30959
31194
  },
31195
+ "PutAutonomyMeGoalsRequest": {
31196
+ "type": "object",
31197
+ "properties": {
31198
+ "goal_ids": {}
31199
+ },
31200
+ "required": [
31201
+ "goal_ids"
31202
+ ],
31203
+ "additionalProperties": false
31204
+ },
31205
+ "PutAutonomyMeGoalsResponse": {
31206
+ "type": "object",
31207
+ "properties": {
31208
+ "goals": {}
31209
+ },
31210
+ "required": [
31211
+ "goals"
31212
+ ]
31213
+ },
30960
31214
  "PutCopyDeskPagesPageIdDraftRequest": {
30961
31215
  "type": "object",
30962
31216
  "properties": {
@@ -31293,9 +31547,9 @@
31293
31547
  "description": "A required dependency/feature is not configured or is temporarily down."
31294
31548
  }
31295
31549
  },
31296
- "x-endpoint-count": 489,
31297
- "x-schema-count": 519,
31550
+ "x-endpoint-count": 493,
31551
+ "x-schema-count": 524,
31298
31552
  "x-undocumented-bodies": 12,
31299
- "x-response-schemas": 347,
31553
+ "x-response-schemas": 349,
31300
31554
  "x-generated-by": "scripts/gds/gen-api-docs.js"
31301
31555
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Bongos API reference
4
4
 
5
- > **Generated from the live route files** — the route file is authoritative. 489 endpoints across 90 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 493 endpoints across 91 route files.
6
6
  > Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
7
7
 
8
8
  Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust-boundary-server-enforced-permissions.md)): `public` < `any-builder` < `metic+archon` < `archon`.
@@ -81,18 +81,21 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
81
81
  | GET | `/api/bongos/auth/web/handoff` | `public` | — | GET /auth/web/handoff?code=&return= — the far side of the one-time session handoff (task 1004357). |
82
82
  | GET | `/api/bongos/auth/web/start` | `public` | — | /auth/web — browser flow (used by the /builders page). |
83
83
 
84
- ## `autonomy` (9)
84
+ ## `autonomy` (12)
85
85
 
86
86
  | Method | Path | Rank | Body | Description |
87
87
  |---|---|---|---|---|
88
+ | POST | `/api/bongos/autonomy/builders/:builderId/pause` | `archon` | `paused`, `reason` | The owner pauses or resumes ONE builder's runner without throwing the master switch. |
88
89
  | GET | `/api/bongos/autonomy/fence` | `any-builder` | — | The runner's own read, every iteration. |
89
90
  | POST | `/api/bongos/autonomy/fence` | `archon` | `enabled`, `reason` | The kill switch. |
90
91
  | POST | `/api/bongos/autonomy/fence/goals` | `archon` | `goal_id`, `note` | Add a goal to the allowlist. |
91
92
  | DELETE | `/api/bongos/autonomy/fence/goals/:goalId` | `archon` | — | Revoke one. |
92
93
  | POST | `/api/bongos/autonomy/fence/priority` | `archon` | `goal_id` | The priority goal (task 1004453): which allowlisted goal the runner works first. |
93
94
  | POST | `/api/bongos/autonomy/heartbeat` | `any-builder` | `host`, `pid`, `started_at`, `mode`, `consecutive_failures`, `last_event`, `working_task_id`, `working_goal_id`, `head`, `disk_head`, `main_head`, `claude_account` | The runner's check-in, once per loop. |
95
+ | PUT | `/api/bongos/autonomy/me/goals` | `metic+archon` | `goal_ids` | A builder picks which allowlisted goals THEIR runner works. |
94
96
  | GET | `/api/bongos/autonomy/precheck` | `metic+archon` | — | |
95
97
  | GET | `/api/bongos/autonomy/runners` | `any-builder` | — | What the hall renders: the CALLER'S OWN runners, with the pure verdict attached so the page and any future alert cannot disagree about wh… |
98
+ | GET | `/api/bongos/autonomy/runners/all` | `archon` | — | The owner's view of every builder's runners: who, which goals they picked, whether they are paused, and each runner's health — the server… |
96
99
  | GET | `/api/bongos/autonomy/runs` | `metic+archon` | — | The gate's past decisions — did a routine fire, and what did it decide, and why (task 1002669). |
97
100
 
98
101
  ## `backup` (2)
@@ -545,7 +548,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
545
548
  | POST | `/api/bongos/my-projects/invites/:clientId/decline` | `any-builder` | — | decline an invite (delete the pending row) for the caller's OWN account. |
546
549
  | POST | `/api/bongos/my-projects/join` | `any-builder` | `origin`, `note` | request to join a project. |
547
550
 
548
- ## `npm-release` (7)
551
+ ## `npm-release` (8)
549
552
 
550
553
  | Method | Path | Rank | Body | Description |
551
554
  |---|---|---|---|---|
@@ -554,6 +557,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
554
557
  | DELETE | `/api/bongos/npm-release/preview` | `any-builder` | — | |
555
558
  | GET | `/api/bongos/npm-release/preview/enter` | `any-builder` | — | |
556
559
  | GET | `/api/bongos/npm-release/preview/exit` | `any-builder` | — | |
560
+ | POST | `/api/bongos/npm-release/release` | `archon` | `version` | |
557
561
  | GET | `/api/bongos/npm-release/task/:id` | `any-builder` | — | |
558
562
  | GET | `/api/bongos/npm-release/work` | `archon` | — | Query: days (ledger window, default 14, max 60), before + limit (history paging). |
559
563