@bongos/core 1.19.1064 → 1.19.1066

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 (49) hide show
  1. package/.bongos-core.json +96 -46
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +6 -0
  4. package/clients/bongos-client/index.cjs +6 -0
  5. package/clients/bongos-client/index.d.ts +11 -1
  6. package/clients/bongos-client/index.mjs +6 -0
  7. package/docs/adr/0341-the-page-is-the-unit-of-tweak-mode.md +1 -0
  8. package/docs/api/openapi.json +237 -4
  9. package/docs/api-reference.md +5 -2
  10. package/docs/branding-contract.md +1 -1
  11. package/docs/copy-inventory.md +60 -41
  12. package/docs/copy-registry.json +228 -47
  13. package/docs/module-api-changelog.md +4 -0
  14. package/docs/page-inventory.json +11 -2
  15. package/docs/page-readings.json +45 -22
  16. package/modules/copy-desk/page-decisions.js +71 -0
  17. package/modules/copy-desk/page-status.js +100 -2
  18. package/modules/copy-desk/pages.js +30 -0
  19. package/modules/copy-desk/routes/copy-desk.js +156 -2
  20. package/modules/copy-desk/tests/copy_no_cms.mjs +40 -4
  21. package/modules/economy/credits.js +77 -0
  22. package/modules/economy/reward-policy.js +7 -1
  23. package/modules/economy/reward.js +4 -0
  24. package/modules/hall-ui/public/approval-queue-lib.js +156 -0
  25. package/modules/hall-ui/public/approval-queue.css +286 -0
  26. package/modules/hall-ui/public/approval-queue.js +338 -0
  27. package/modules/hall-ui/public/studio.css +33 -0
  28. package/modules/hall-ui/public/studio.html +18 -1
  29. package/modules/hall-ui/public/studio.js +30 -0
  30. package/modules/hall-ui/public/studio.states.json +198 -0
  31. package/modules/hall-ui/records/approval-queue.md +32 -0
  32. package/modules/lifecycle/db-grade.js +80 -58
  33. package/modules/lifecycle/db-ship.js +14 -5
  34. package/modules/lifecycle/github-pr-close.js +41 -0
  35. package/modules/lifecycle/github-push.js +5 -2
  36. package/modules/lifecycle/lifecycle.js +12 -0
  37. package/modules/lifecycle/page-tweak-approve.js +242 -0
  38. package/modules/lifecycle/routes/gate-approvals.js +17 -2
  39. package/package-lock.json +2 -2
  40. package/package.json +1 -1
  41. package/release-notes.json +12 -0
  42. package/scripts/hall-preview/server.js +18 -0
  43. package/src/module-api.js +1 -1
  44. package/tests/artist_page_credit.mjs +272 -0
  45. package/tests/copy_desk_page_approve.mjs +307 -0
  46. package/tests/fixtures/page-ledger.mjs +41 -1
  47. package/tests/gate_approvals.mjs +93 -0
  48. package/tests/hall_approval_queue.mjs +327 -0
  49. package/tests/hall_audit.mjs +4 -0
@@ -4979,6 +4979,37 @@
4979
4979
  ]
4980
4980
  }
4981
4981
  },
4982
+ "/copy-desk/approvals": {
4983
+ "get": {
4984
+ "operationId": "get_copy_desk_approvals",
4985
+ "tags": [
4986
+ "copy-desk"
4987
+ ],
4988
+ "summary": "GET /copy-desk/approvals",
4989
+ "description": "GET /copy-desk/approvals — every round waiting for its artist, oldest applied first, with its position (\"1 of 2\"), the lines it rewrote (and the ones the applier refused), and where its renders are. Any signed-in builder; `can_decide` says whether the caller may approve or send back.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
4990
+ "x-rank": "any-builder",
4991
+ "x-source": "modules/copy-desk/routes/copy-desk.js",
4992
+ "responses": {
4993
+ "200": {
4994
+ "description": "Success."
4995
+ },
4996
+ "400": {
4997
+ "$ref": "#/components/responses/BadRequest"
4998
+ },
4999
+ "401": {
5000
+ "$ref": "#/components/responses/Unauthorized"
5001
+ },
5002
+ "403": {
5003
+ "$ref": "#/components/responses/Forbidden"
5004
+ }
5005
+ },
5006
+ "security": [
5007
+ {
5008
+ "builderSession": []
5009
+ }
5010
+ ]
5011
+ }
5012
+ },
4982
5013
  "/copy-desk/flags": {
4983
5014
  "post": {
4984
5015
  "operationId": "post_copy_desk_flags",
@@ -5198,6 +5229,69 @@
5198
5229
  ]
5199
5230
  }
5200
5231
  },
5232
+ "/copy-desk/pages/{pageId}/approve": {
5233
+ "post": {
5234
+ "operationId": "post_copy_desk_pages_pageId_approve",
5235
+ "tags": [
5236
+ "copy-desk"
5237
+ ],
5238
+ "summary": "POST /copy-desk/pages/:pageId/approve",
5239
+ "description": "------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/approve — the held pass goes on to land. Body: { task_id? } (the round the artist looked at). The port promotes completed -> confirmed with the rewards the hold skipped and nudges the merge; the reconciler lands it otherwise. The count goes up when it ships. 200 approved · 409 not_waiting · 409 round_moved · 403 not_an_artist -------------------------------------------------------------------------\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5240
+ "x-rank": "any-builder",
5241
+ "x-source": "modules/copy-desk/routes/copy-desk.js",
5242
+ "parameters": [
5243
+ {
5244
+ "name": "pageId",
5245
+ "in": "path",
5246
+ "required": true,
5247
+ "schema": {
5248
+ "type": "string"
5249
+ },
5250
+ "description": "Path parameter `pageId`."
5251
+ }
5252
+ ],
5253
+ "requestBody": {
5254
+ "required": false,
5255
+ "content": {
5256
+ "application/json": {
5257
+ "schema": {
5258
+ "$ref": "#/components/schemas/PostCopyDeskPagesPageIdApproveRequest"
5259
+ }
5260
+ }
5261
+ },
5262
+ "x-validated": true
5263
+ },
5264
+ "responses": {
5265
+ "200": {
5266
+ "description": "Success.",
5267
+ "content": {
5268
+ "application/json": {
5269
+ "schema": {
5270
+ "$ref": "#/components/schemas/PostCopyDeskPagesPageIdApproveResponse"
5271
+ }
5272
+ }
5273
+ }
5274
+ },
5275
+ "400": {
5276
+ "$ref": "#/components/responses/ValidationFailed"
5277
+ },
5278
+ "401": {
5279
+ "$ref": "#/components/responses/Unauthorized"
5280
+ },
5281
+ "403": {
5282
+ "$ref": "#/components/responses/Forbidden"
5283
+ },
5284
+ "404": {
5285
+ "$ref": "#/components/responses/NotFound"
5286
+ }
5287
+ },
5288
+ "security": [
5289
+ {
5290
+ "builderSession": []
5291
+ }
5292
+ ]
5293
+ }
5294
+ },
5201
5295
  "/copy-desk/pages/{pageId}/asks": {
5202
5296
  "post": {
5203
5297
  "operationId": "post_copy_desk_pages_pageId_asks",
@@ -5525,6 +5619,69 @@
5525
5619
  ]
5526
5620
  }
5527
5621
  },
5622
+ "/copy-desk/pages/{pageId}/send-back": {
5623
+ "post": {
5624
+ "operationId": "post_copy_desk_pages_pageId_send_back",
5625
+ "tags": [
5626
+ "copy-desk"
5627
+ ],
5628
+ "summary": "POST /copy-desk/pages/:pageId/send-back",
5629
+ "description": "------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/send-back — back to the /tweak queue with a note (ADR 0341 D7). Body: { note, task_id? }. The note is one line of at least 10 characters (pages.normalizeSentBackNote). The port appends a page-tweak-sent-back block { at, by, note }, releases any open claim, drops the round's grade row, returns the task to ready and closes the unmerged PR, so the round reads `submitted` again. 200 sent_back · 400 note_too_short / note_too_long · 409 not_waiting · 409 round_moved · 403 not_an_artist -------------------------------------------------------------------------\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5630
+ "x-rank": "any-builder",
5631
+ "x-source": "modules/copy-desk/routes/copy-desk.js",
5632
+ "parameters": [
5633
+ {
5634
+ "name": "pageId",
5635
+ "in": "path",
5636
+ "required": true,
5637
+ "schema": {
5638
+ "type": "string"
5639
+ },
5640
+ "description": "Path parameter `pageId`."
5641
+ }
5642
+ ],
5643
+ "requestBody": {
5644
+ "required": true,
5645
+ "content": {
5646
+ "application/json": {
5647
+ "schema": {
5648
+ "$ref": "#/components/schemas/PostCopyDeskPagesPageIdSendBackRequest"
5649
+ }
5650
+ }
5651
+ },
5652
+ "x-validated": true
5653
+ },
5654
+ "responses": {
5655
+ "200": {
5656
+ "description": "Success.",
5657
+ "content": {
5658
+ "application/json": {
5659
+ "schema": {
5660
+ "$ref": "#/components/schemas/PostCopyDeskPagesPageIdSendBackResponse"
5661
+ }
5662
+ }
5663
+ }
5664
+ },
5665
+ "400": {
5666
+ "$ref": "#/components/responses/ValidationFailed"
5667
+ },
5668
+ "401": {
5669
+ "$ref": "#/components/responses/Unauthorized"
5670
+ },
5671
+ "403": {
5672
+ "$ref": "#/components/responses/Forbidden"
5673
+ },
5674
+ "404": {
5675
+ "$ref": "#/components/responses/NotFound"
5676
+ }
5677
+ },
5678
+ "security": [
5679
+ {
5680
+ "builderSession": []
5681
+ }
5682
+ ]
5683
+ }
5684
+ },
5528
5685
  "/copy-desk/pages/{pageId}/submit": {
5529
5686
  "post": {
5530
5687
  "operationId": "post_copy_desk_pages_pageId_submit",
@@ -25354,6 +25511,40 @@
25354
25511
  "flag"
25355
25512
  ]
25356
25513
  },
25514
+ "PostCopyDeskPagesPageIdApproveRequest": {
25515
+ "type": "object",
25516
+ "properties": {
25517
+ "task_id": {
25518
+ "type": "string",
25519
+ "minLength": 1,
25520
+ "maxLength": 20
25521
+ }
25522
+ },
25523
+ "additionalProperties": false
25524
+ },
25525
+ "PostCopyDeskPagesPageIdApproveResponse": {
25526
+ "type": "object",
25527
+ "properties": {
25528
+ "ok": {
25529
+ "type": "boolean"
25530
+ },
25531
+ "outcome": {},
25532
+ "page_id": {},
25533
+ "round": {},
25534
+ "status_after": {},
25535
+ "land": {},
25536
+ "next": {}
25537
+ },
25538
+ "required": [
25539
+ "ok",
25540
+ "outcome",
25541
+ "page_id",
25542
+ "round",
25543
+ "status_after",
25544
+ "land",
25545
+ "next"
25546
+ ]
25547
+ },
25357
25548
  "PostCopyDeskPagesPageIdAsksRequest": {
25358
25549
  "type": "object",
25359
25550
  "properties": {
@@ -25390,6 +25581,47 @@
25390
25581
  "merge"
25391
25582
  ]
25392
25583
  },
25584
+ "PostCopyDeskPagesPageIdSendBackRequest": {
25585
+ "type": "object",
25586
+ "properties": {
25587
+ "note": {
25588
+ "type": "string",
25589
+ "minLength": 1
25590
+ },
25591
+ "task_id": {
25592
+ "type": "string",
25593
+ "minLength": 1,
25594
+ "maxLength": 20
25595
+ }
25596
+ },
25597
+ "required": [
25598
+ "note"
25599
+ ],
25600
+ "additionalProperties": false
25601
+ },
25602
+ "PostCopyDeskPagesPageIdSendBackResponse": {
25603
+ "type": "object",
25604
+ "properties": {
25605
+ "ok": {
25606
+ "type": "boolean"
25607
+ },
25608
+ "outcome": {},
25609
+ "page_id": {},
25610
+ "round": {},
25611
+ "sent_back": {},
25612
+ "pr": {},
25613
+ "next": {}
25614
+ },
25615
+ "required": [
25616
+ "ok",
25617
+ "outcome",
25618
+ "page_id",
25619
+ "round",
25620
+ "sent_back",
25621
+ "pr",
25622
+ "next"
25623
+ ]
25624
+ },
25393
25625
  "PostCopyDeskProposalsRequest": {
25394
25626
  "type": "object",
25395
25627
  "properties": {
@@ -25589,7 +25821,8 @@
25589
25821
  "status_set": {
25590
25822
  "type": "boolean"
25591
25823
  },
25592
- "recheck": {}
25824
+ "recheck": {},
25825
+ "held_for_artist": {}
25593
25826
  },
25594
25827
  "required": [
25595
25828
  "ok",
@@ -28973,9 +29206,9 @@
28973
29206
  "description": "A required dependency/feature is not configured or is temporarily down."
28974
29207
  }
28975
29208
  },
28976
- "x-endpoint-count": 457,
28977
- "x-schema-count": 491,
29209
+ "x-endpoint-count": 460,
29210
+ "x-schema-count": 495,
28978
29211
  "x-undocumented-bodies": 10,
28979
- "x-response-schemas": 336,
29212
+ "x-response-schemas": 338,
28980
29213
  "x-generated-by": "scripts/gds/gen-api-docs.js"
28981
29214
  }
@@ -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. 457 endpoints across 76 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 460 endpoints across 76 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`.
@@ -210,21 +210,24 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
210
210
  | GET | `/api/bongos/connections/requests` | `any-builder` | — | MY pending requests, both directions (own data). |
211
211
  | GET | `/api/bongos/connections/suggestions` | `any-builder` | — | "builders you may know" (R21, task 1002297; ADR 0202 D5). |
212
212
 
213
- ## `copy-desk` (16)
213
+ ## `copy-desk` (19)
214
214
 
215
215
  | Method | Path | Rank | Body | Description |
216
216
  |---|---|---|---|---|
217
+ | GET | `/api/bongos/copy-desk/approvals` | `any-builder` | — | GET /copy-desk/approvals — every round waiting for its artist, oldest applied first, with its position ("1 of 2"), the lines it rewrote (… |
217
218
  | POST | `/api/bongos/copy-desk/flags` | `any-builder` | `scope`, `surface`, `string_id`, `reason`, `kind` | ------------------------------------------------------------------------- POST /copy-desk/flags — file a flag. |
218
219
  | POST | `/api/bongos/copy-desk/flags/:id/close` | `any-builder` | `status`, `resolution_note`, `resolved_task_id` | ------------------------------------------------------------------------- POST /copy-desk/flags/:id/close — resolve or dismiss. |
219
220
  | GET | `/api/bongos/copy-desk/next` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/next — the Tweak/CopyWrite Flow's recommendation… |
220
221
  | GET | `/api/bongos/copy-desk/pages` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/pages — every page's status, count and drift, pl… |
221
222
  | GET | `/api/bongos/copy-desk/pages/:pageId` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/pages/:pageId — one page: status, changelog, the… |
223
+ | POST | `/api/bongos/copy-desk/pages/:pageId/approve` | `any-builder` | `task_id` | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/approve — the held pass goes on t… |
222
224
  | POST | `/api/bongos/copy-desk/pages/:pageId/asks` | `any-builder` | `reason` | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/asks — ask for a page (task 10043… |
223
225
  | POST | `/api/bongos/copy-desk/pages/:pageId/claim` | `any-builder` | validated | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/claim — claim a page's tweak (tas… |
224
226
  | GET | `/api/bongos/copy-desk/pages/:pageId/draft` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/pages/:pageId/draft — what the tweak editor open… |
225
227
  | PUT | `/api/bongos/copy-desk/pages/:pageId/draft` | `any-builder` | `reading_hash`, `lines` | ------------------------------------------------------------------------- PUT /copy-desk/pages/:pageId/draft — autosave the artist's draf… |
226
228
  | GET | `/api/bongos/copy-desk/pages/:pageId/draft.docx` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/pages/:pageId/draft.docx — download the page's w… |
227
229
  | POST | `/api/bongos/copy-desk/pages/:pageId/draft.docx` | `any-builder` | _undocumented_ | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/draft.docx — upload the Word file… |
230
+ | POST | `/api/bongos/copy-desk/pages/:pageId/send-back` | `any-builder` | `note`, `task_id` | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/send-back — back to the /tweak qu… |
228
231
  | POST | `/api/bongos/copy-desk/pages/:pageId/submit` | `any-builder` | validated | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/submit — freeze the draft and que… |
229
232
  | POST | `/api/bongos/copy-desk/proposals` | `any-builder` | `string_id`, `proposed_text`, `why`, `file`, `line`, `flag_id` | ------------------------------------------------------------------------- POST /copy-desk/proposals — an artist proposes new wording, and… |
230
233
  | GET | `/api/bongos/copy-desk/queue` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/queue — the artist's working list. |
@@ -36,7 +36,7 @@ env override → instance config (config/branding.json) → neutral star
36
36
  | `repo` | `{ owner, name }` GitHub binding. |
37
37
  | `db.database` | DB name Bongos pool connects to when neither `DATABASE_URL` nor `PGHOST`/`PGDATABASE` is set (`src/bongos/pool.js`, ADR 0062 §5). `null` in the neutral starter = **fail loud** rather than silently target a host DB. |
38
38
  | `currency` | `{ label, symbol }` — the reward unit label (e.g. "example"). Display only. |
39
- | `reward` | `{ marginPct, usdPeg, mode }` — the per-instance reward POLICY the economy module reads ([ADR 0054](adr/0054-session-token-reward-cost-plus.md) + ADR 0146, tasks 2009/1002270): the cost-plus margin percent (default `20`), the example-per-USD peg (default `1`), and `mode` — `"cost-plus-and-estimate"` (default; pay both the per-task author estimate AND the cost-plus session reward) or `"cost-plus-only"` (suppress the per-task estimate payout; the cost-plus session reward is the sole equity reward). A committed, code-reviewed change — not a live UI knob. Omit ⇒ code defaults (20% margin, 1:1 peg, pay both streams). |
39
+ | `reward` | `{ marginPct, usdPeg, mode }` — the per-instance reward POLICY the economy module reads ([ADR 0054](adr/0054-session-token-reward-cost-plus.md) + ADR 0146, tasks 2009/1002270): the cost-plus margin percent (default `20`), the example-per-USD peg (default `1`), and `mode` — `"cost-plus-and-estimate"` (default; pay both the per-task author estimate AND the cost-plus session reward) or `"cost-plus-only"` (suppress the per-task estimate payout; the cost-plus session reward is the sole equity reward). Two per-craft lanes sit beside `mode` and are not derived from it: `ideatorCredit` ([ADR 0172](adr/0172-per-craft-compensation-ideator-credit-lane.md)) and `artistCredit` ([ADR 0341](adr/0341-the-page-is-the-unit-of-tweak-mode.md) D10, an approved page tweak pays its artist), each default on and withheld only by an explicit `false`. A committed, code-reviewed change — not a live UI knob. Omit ⇒ code defaults (20% margin, 1:1 peg, pay both streams, both lanes on). |
40
40
  | `models` | `{ main, subagentDefault, subagentRoutine }` — the per-instance subagent model-allocation DEFAULT the builder-settings module reads (task 2011): the tier for the main session, subagent-default work, and routine plumbing (tiers: `haiku`/`sonnet`/`opus`/`fable`). A per-builder override resolves over this. Omit ⇒ code defaults (`opus`/`opus`/`haiku`). |
41
41
  | `tracks` | The configurable version-track set (replaces the hardcoded `product\|internal`). |
42
42
  | `theme` | `{ palette, mode, ui }` — palette file ref + theme mode, plus `ui`, the WEB look `themeMarkup()` splices into every served page as a plain `:root` after the page's stylesheet: `colors` (the thirteen contract tokens — **light-mode values**; each stylesheet derives its own dark tier from them at `:root[data-mode="dark"]` + its `prefers-color-scheme` twin, which outrank the pack), `fonts` (`display`, `body`, `links`), `favicon`, and `backdrop` — a `body{background:…}` rule that outranks every sheet in **both** modes, so a dual-mode world sets it to `var(--bg)` (the neutral pack does since [task 1003298](https://cloudbongos.com/builders#/task/1003298), ADR 0196) rather than a literal. The neutral values are the chrome world's; `config/design-tokens.neutral.json` must mirror `colors` + `fonts` key for key (`tests/design_tokens_sync.mjs`), and the world's derived recipes are recorded in `DESIGN.md`. The ui-design module's **style library** (`modules/ui-design/styles/`, [ADR 0219](adr/0219-a-look-is-a-branding-pack-the-style-library.md)) ships ready-made `theme.ui` blocks (looks) an instance copies into this field; every served sheet reads only these fifteen, so a look re-themes every surface with no page edit. |