@bongos/core 1.19.1059 → 1.19.1061

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.
package/.bongos-core.json CHANGED
@@ -2,22 +2,22 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.1059",
6
- "core_contract": "1.19.1059",
7
- "source_commit": "77525594aafb82e0be5f53d111e1d751ed6945cc",
5
+ "core_version": "1.19.1061",
6
+ "core_contract": "1.19.1061",
7
+ "source_commit": "1cc2c2cdca684d17445332667885541d1bd1abbc",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-28T11:26:07.315Z",
9
+ "built_at": "2026-09-28T12:38:11.098Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 543,
13
13
  "agent_docs_stubbed": 26,
14
- "functional_verbatim": 2525,
14
+ "functional_verbatim": 2531,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 3095,
20
- "tree_sha256": "27e342154726c2063d49121ee1ef6a47f3125fc8673ba3a3ed328c8a15fc25db",
19
+ "file_count": 3101,
20
+ "tree_sha256": "22d7d908ffbc96ccc7866b4212aabb6062dfb4b6ffa915ddaa0153125d8aa4dd",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -317,12 +317,12 @@
317
317
  {
318
318
  "path": "clients/bongos-client/README.md",
319
319
  "mode": "0000644",
320
- "sha256": "18f34899047600dc6f4301d3ee6728e7bf01216bb0aad0d3779c90c24878c417"
320
+ "sha256": "a430ee71b5a2698346d4917245863dfc847cd31091dfa5de9a01ef7d21abd1f7"
321
321
  },
322
322
  {
323
323
  "path": "clients/bongos-client/bongos-client.global.js",
324
324
  "mode": "0000644",
325
- "sha256": "cb4119d5434eb11476fb56ab5f3ad7cba19a04636669def7a9642abdfb379410"
325
+ "sha256": "86d62d8e000364d5c05ef0eced49f1fa165c923dc7892fe82d918c21864de616"
326
326
  },
327
327
  {
328
328
  "path": "clients/bongos-client/examples/hello-world.mjs",
@@ -332,17 +332,17 @@
332
332
  {
333
333
  "path": "clients/bongos-client/index.cjs",
334
334
  "mode": "0000644",
335
- "sha256": "3d0b0cee2b777554c3289c54a1986bd65ee3a51b83d26535384b505866f56d5c"
335
+ "sha256": "e0e84783a89af88a81251931ae7702e0c0302001446bf5b33d7de30bd4c9e264"
336
336
  },
337
337
  {
338
338
  "path": "clients/bongos-client/index.d.ts",
339
339
  "mode": "0000644",
340
- "sha256": "df7d595c5ed10a4472cc3fc7bf3254e8b90eca5651394177b26dcbe3327fcf1e"
340
+ "sha256": "9fdc897116e58b93d39b940c5ae20108825bc88d67dad1de11d980f943a021c0"
341
341
  },
342
342
  {
343
343
  "path": "clients/bongos-client/index.mjs",
344
344
  "mode": "0000644",
345
- "sha256": "b211a8a2072874c86fa7d1c948a8e0313b76191c69fd4d044e2704aada198113"
345
+ "sha256": "102dae082b630a9d2613d1f5dab5b128748a005304f066ce3f36f8ff5166aa04"
346
346
  },
347
347
  {
348
348
  "path": "clients/bongos-client/package.json",
@@ -2177,12 +2177,12 @@
2177
2177
  {
2178
2178
  "path": "docs/api-reference.md",
2179
2179
  "mode": "0000644",
2180
- "sha256": "e79005662b3fc53fed213d29c07885df5563a1319e978387d84fb30295a609c3"
2180
+ "sha256": "66487b94a7ca2646daa4fbe24159396d48fbcf10f2adc9c14b9e43fc86233b56"
2181
2181
  },
2182
2182
  {
2183
2183
  "path": "docs/api/openapi.json",
2184
2184
  "mode": "0000644",
2185
- "sha256": "fd26c908294adf589bfe05b6f1432b74bbb07f4cd5c0dce4d89e9b052e3dbdfa"
2185
+ "sha256": "258b4baf4671e59e66464c47193f54a91d34a3a678dcc9db0955053f7f86e48b"
2186
2186
  },
2187
2187
  {
2188
2188
  "path": "docs/architecture.md",
@@ -2742,7 +2742,7 @@
2742
2742
  {
2743
2743
  "path": "docs/module-api-changelog.md",
2744
2744
  "mode": "0000644",
2745
- "sha256": "e503dd3babb557fcc2cdd366604e50c845d3264f29a6fbffd8c31b9a40cf6ae9"
2745
+ "sha256": "a47ac184c604897dd657f4995f4e278303d378747164bc9540b0937eab19186e"
2746
2746
  },
2747
2747
  {
2748
2748
  "path": "docs/modules-contract.md",
@@ -4112,7 +4112,7 @@
4112
4112
  {
4113
4113
  "path": "modules/copy-desk/flags.js",
4114
4114
  "mode": "0000644",
4115
- "sha256": "292f0d3461855552efc25cc5207dd4d58db38ef4c1b6eadcbb55521f89e6fa5e"
4115
+ "sha256": "ca617aef2c209f89c57acf2db7772b27f0bb7e790afb48dc940822422ec8ad81"
4116
4116
  },
4117
4117
  {
4118
4118
  "path": "modules/copy-desk/migrations/copy_desk_001_flags.sql",
@@ -4137,12 +4137,12 @@
4137
4137
  {
4138
4138
  "path": "modules/copy-desk/page-status.js",
4139
4139
  "mode": "0000644",
4140
- "sha256": "63af13ad05f0b2479eb9488f542f3f0dade74273de41e422583eebe070359271"
4140
+ "sha256": "fe85e899abb8524b36ef7187a8a2b5b127ea87342c378a32b95a644d18a83021"
4141
4141
  },
4142
4142
  {
4143
4143
  "path": "modules/copy-desk/pages.js",
4144
4144
  "mode": "0000644",
4145
- "sha256": "671edb87faad28217c30abdcfff2c110d9b692f0da0f2d18af975d34d42b782e"
4145
+ "sha256": "ba89a35e225a41e94e20a21e716a3d83ab15081c2f9d6f6718394c25b37ea305"
4146
4146
  },
4147
4147
  {
4148
4148
  "path": "modules/copy-desk/proposals.js",
@@ -4157,7 +4157,7 @@
4157
4157
  {
4158
4158
  "path": "modules/copy-desk/routes/copy-desk.js",
4159
4159
  "mode": "0000644",
4160
- "sha256": "4c7bab355d8410ec755f9677914b97132edc5be7c61b0aeebbf5b14abd2a3b42"
4160
+ "sha256": "92170c36251df8a1606d87dcbd057bccc167f348f39d2705872934f24411c7d7"
4161
4161
  },
4162
4162
  {
4163
4163
  "path": "modules/copy-desk/tests/copy_flags.mjs",
@@ -4167,7 +4167,17 @@
4167
4167
  {
4168
4168
  "path": "modules/copy-desk/tests/copy_no_cms.mjs",
4169
4169
  "mode": "0000644",
4170
- "sha256": "17ad6640e97dde18273ccd5c533b6910d490bfad970da16fd0712c20a8b5f7f3"
4170
+ "sha256": "b04b745bfc010ed86d7187c22f067bb8ecaaa24a095420a01f2b37806f283d48"
4171
+ },
4172
+ {
4173
+ "path": "modules/copy-desk/tests/copy_page_draft.mjs",
4174
+ "mode": "0000644",
4175
+ "sha256": "7bae773b6f8e3c4d5dced4d689237f59d421fc34f9d6c809d50e81f610e9eafb"
4176
+ },
4177
+ {
4178
+ "path": "modules/copy-desk/tests/copy_page_next.mjs",
4179
+ "mode": "0000644",
4180
+ "sha256": "d82db6db97b22a88a83b4cf9bac7724a411dc7831b08cacd5548c0ac367ad3b9"
4171
4181
  },
4172
4182
  {
4173
4183
  "path": "modules/copy-desk/tests/copy_page_status.mjs",
@@ -6127,7 +6137,7 @@
6127
6137
  {
6128
6138
  "path": "modules/lifecycle/lifecycle.js",
6129
6139
  "mode": "0000644",
6130
- "sha256": "05edef42162cff680d96b084805959741be5a9ec09b18c87fdbfab6ff65458e0"
6140
+ "sha256": "8ed95b63975ec4aceb34ddeb31fa147194b38c26242530c83a5ed144214b5150"
6131
6141
  },
6132
6142
  {
6133
6143
  "path": "modules/lifecycle/merge-lock.js",
@@ -6212,7 +6222,12 @@
6212
6222
  {
6213
6223
  "path": "modules/lifecycle/page-tweak-reads.js",
6214
6224
  "mode": "0000644",
6215
- "sha256": "ed622f53097f8f0595c885c796ca597c6d96004cca82d884c30c97f43afc104e"
6225
+ "sha256": "016329bc9dadda1e1b1dce86aa02aa7c7f259cc56708ca12030ea601ea63e7a0"
6226
+ },
6227
+ {
6228
+ "path": "modules/lifecycle/page-tweak-write.js",
6229
+ "mode": "0000644",
6230
+ "sha256": "a13c01e96c5ae09837b9d599a66b23765f6d6f16cc29b11ca897da4f497d0b0d"
6216
6231
  },
6217
6232
  {
6218
6233
  "path": "modules/lifecycle/pg-constraint-fail.js",
@@ -8517,12 +8532,12 @@
8517
8532
  {
8518
8533
  "path": "package-lock.json",
8519
8534
  "mode": "0000644",
8520
- "sha256": "cd48c5b838a56b6fb70ccedf866a234037b46a049f027facc60d0a925eabe5f9"
8535
+ "sha256": "dd4068cbb235742769c4bda2d8d49dd955c266e5986844fc471ef12416166730"
8521
8536
  },
8522
8537
  {
8523
8538
  "path": "package.json",
8524
8539
  "mode": "0000644",
8525
- "sha256": "c2e9d52b540b2adbe2e9e7b8ae333d2b621add895a6280e1cc6d7c961f26b833"
8540
+ "sha256": "c3abc1f3e3b321375820e92c627d7f7aeb13a87259f0783aea211386c68d8267"
8526
8541
  },
8527
8542
  {
8528
8543
  "path": "public-docs/index.html",
@@ -8542,7 +8557,7 @@
8542
8557
  {
8543
8558
  "path": "release-notes.json",
8544
8559
  "mode": "0000644",
8545
- "sha256": "77adcb2aa4e1aeed40c59698b77423095609e35589148c112b0a7196a5fc4542"
8560
+ "sha256": "d77397164aba5ff244fe0ddbcd9a4d7e8e327b357a37e6cb48bdfbe1bbbba7a6"
8546
8561
  },
8547
8562
  {
8548
8563
  "path": "scripts/bongos-mcp.js",
@@ -10627,7 +10642,7 @@
10627
10642
  {
10628
10643
  "path": "src/module-api.js",
10629
10644
  "mode": "0000644",
10630
- "sha256": "d599f052a4dddddb6bc9ca72b7b97c99ba2c2e20e1d577cc8afdbfb2391289a5"
10645
+ "sha256": "56850953ea4d6876e68096995c35e9b9eaa1b44f092715c4aba8677e89c889d3"
10631
10646
  },
10632
10647
  {
10633
10648
  "path": "src/module-loader/catalog.js",
@@ -11577,18 +11592,28 @@
11577
11592
  {
11578
11593
  "path": "tests/copy_desk_flags_db.mjs",
11579
11594
  "mode": "0000644",
11580
- "sha256": "b016c0017adfa95de453d418e81e1c22a2a7193418f05f05845a3212941bd074"
11595
+ "sha256": "739bbd623955742864ac712a5f119968ebac671c005054a07a8521c7770a929b"
11581
11596
  },
11582
11597
  {
11583
11598
  "path": "tests/copy_desk_page_claim.mjs",
11584
11599
  "mode": "0000644",
11585
- "sha256": "18b0e3cd3384226fe2278a7094e45b849e0f43dc41269b40fa5487fd315e0f20"
11600
+ "sha256": "af6cdac77b90aad511a603757e12d7ffefaa7fdbcdd14aefd70ad49e3cd193fe"
11601
+ },
11602
+ {
11603
+ "path": "tests/copy_desk_page_next.mjs",
11604
+ "mode": "0000644",
11605
+ "sha256": "d9827f75b542ce1a3fe9bfe9e3d5cd8ecaaed4691d611dc73617d280ec6cf292"
11586
11606
  },
11587
11607
  {
11588
11608
  "path": "tests/copy_desk_page_reads.mjs",
11589
11609
  "mode": "0000644",
11590
11610
  "sha256": "29c591eb22b17fb86a3bff894d362f1372e41d1d0e06e3751f36da90184a425a"
11591
11611
  },
11612
+ {
11613
+ "path": "tests/copy_desk_page_submit.mjs",
11614
+ "mode": "0000644",
11615
+ "sha256": "c77d8c60449bad805d048ec78e43169b5ec87283a3f91e29edba9e88352f4c51"
11616
+ },
11592
11617
  {
11593
11618
  "path": "tests/copy_inventory.mjs",
11594
11619
  "mode": "0000644",
@@ -12069,6 +12094,11 @@
12069
12094
  "mode": "0000644",
12070
12095
  "sha256": "2f532cacb06f0f074c15101c16578f3183104042644d6c8aa0d2e80fdb425b2f"
12071
12096
  },
12097
+ {
12098
+ "path": "tests/fixtures/page-ledger.mjs",
12099
+ "mode": "0000644",
12100
+ "sha256": "9087b5a76ddc3d11e5b7a8bf23ac56c824e763e63d302ac457d9515707f0c7a5"
12101
+ },
12072
12102
  {
12073
12103
  "path": "tests/fixtures/session-506-digest.json",
12074
12104
  "mode": "0000644",
@@ -5,7 +5,7 @@ A **generated**, zero-dependency typed client for the Bongos API — produced fr
5
5
  by hand; it regenerates when the spec changes, so it can never drift from the routes.
6
6
 
7
7
  - API version: **v1** (served at `/api/bongos/v1`)
8
- - 448 operations across 68 resource groups
8
+ - 451 operations across 68 resource groups
9
9
 
10
10
  ## Use it from your project
11
11
 
@@ -343,6 +343,8 @@ function createClient(opts = {}) {
343
343
  postCopyDeskFlags: (args) => request("POST", "/copy-desk/flags", { hasBody: true }, args),
344
344
  // POST /copy-desk/flags/{id}/close — rank: any-builder — POST /copy-desk/flags/:id/close
345
345
  postCopyDeskFlagsIdClose: (args) => request("POST", "/copy-desk/flags/{id}/close", { hasBody: true }, args),
346
+ // GET /copy-desk/next — rank: any-builder — GET /copy-desk/next
347
+ getCopyDeskNext: (args) => request("GET", "/copy-desk/next", { hasBody: false }, args),
346
348
  // GET /copy-desk/pages — rank: any-builder — GET /copy-desk/pages
347
349
  getCopyDeskPages: (args) => request("GET", "/copy-desk/pages", { hasBody: false }, args),
348
350
  // GET /copy-desk/pages/{pageId} — rank: any-builder — GET /copy-desk/pages/:pageId
@@ -351,6 +353,10 @@ function createClient(opts = {}) {
351
353
  postCopyDeskPagesPageIdAsks: (args) => request("POST", "/copy-desk/pages/{pageId}/asks", { hasBody: true }, args),
352
354
  // POST /copy-desk/pages/{pageId}/claim — rank: any-builder — POST /copy-desk/pages/:pageId/claim
353
355
  postCopyDeskPagesPageIdClaim: (args) => request("POST", "/copy-desk/pages/{pageId}/claim", { hasBody: true }, args),
356
+ // PUT /copy-desk/pages/{pageId}/draft — rank: any-builder — PUT /copy-desk/pages/:pageId/draft
357
+ putCopyDeskPagesPageIdDraft: (args) => request("PUT", "/copy-desk/pages/{pageId}/draft", { hasBody: true }, args),
358
+ // POST /copy-desk/pages/{pageId}/submit — rank: any-builder — POST /copy-desk/pages/:pageId/submit
359
+ postCopyDeskPagesPageIdSubmit: (args) => request("POST", "/copy-desk/pages/{pageId}/submit", { hasBody: true }, args),
354
360
  // POST /copy-desk/proposals — rank: any-builder — POST /copy-desk/proposals
355
361
  postCopyDeskProposals: (args) => request("POST", "/copy-desk/proposals", { hasBody: true }, args),
356
362
  // GET /copy-desk/queue — rank: any-builder — GET /copy-desk/queue
@@ -342,6 +342,8 @@ function createClient(opts = {}) {
342
342
  postCopyDeskFlags: (args) => request("POST", "/copy-desk/flags", { hasBody: true }, args),
343
343
  // POST /copy-desk/flags/{id}/close — rank: any-builder — POST /copy-desk/flags/:id/close
344
344
  postCopyDeskFlagsIdClose: (args) => request("POST", "/copy-desk/flags/{id}/close", { hasBody: true }, args),
345
+ // GET /copy-desk/next — rank: any-builder — GET /copy-desk/next
346
+ getCopyDeskNext: (args) => request("GET", "/copy-desk/next", { hasBody: false }, args),
345
347
  // GET /copy-desk/pages — rank: any-builder — GET /copy-desk/pages
346
348
  getCopyDeskPages: (args) => request("GET", "/copy-desk/pages", { hasBody: false }, args),
347
349
  // GET /copy-desk/pages/{pageId} — rank: any-builder — GET /copy-desk/pages/:pageId
@@ -350,6 +352,10 @@ function createClient(opts = {}) {
350
352
  postCopyDeskPagesPageIdAsks: (args) => request("POST", "/copy-desk/pages/{pageId}/asks", { hasBody: true }, args),
351
353
  // POST /copy-desk/pages/{pageId}/claim — rank: any-builder — POST /copy-desk/pages/:pageId/claim
352
354
  postCopyDeskPagesPageIdClaim: (args) => request("POST", "/copy-desk/pages/{pageId}/claim", { hasBody: true }, args),
355
+ // PUT /copy-desk/pages/{pageId}/draft — rank: any-builder — PUT /copy-desk/pages/:pageId/draft
356
+ putCopyDeskPagesPageIdDraft: (args) => request("PUT", "/copy-desk/pages/{pageId}/draft", { hasBody: true }, args),
357
+ // POST /copy-desk/pages/{pageId}/submit — rank: any-builder — POST /copy-desk/pages/:pageId/submit
358
+ postCopyDeskPagesPageIdSubmit: (args) => request("POST", "/copy-desk/pages/{pageId}/submit", { hasBody: true }, args),
353
359
  // POST /copy-desk/proposals — rank: any-builder — POST /copy-desk/proposals
354
360
  postCopyDeskProposals: (args) => request("POST", "/copy-desk/proposals", { hasBody: true }, args),
355
361
  // GET /copy-desk/queue — rank: any-builder — GET /copy-desk/queue
@@ -481,6 +481,8 @@ export interface PostVersionsIdDoneWhenRequest { criterion_id: string; criterion
481
481
  export interface PostVersionsIdDoneWhenResponse { ok: boolean; criterion: unknown }
482
482
  export interface PostVersionsRequest { id: string; name: string; status?: string; done_when?: string; scope_doc_path?: string; criteria?: unknown[]; first_goal?: Record<string, unknown> }
483
483
  export interface PostVersionsResponse { version: unknown; goal: unknown; criteria: unknown }
484
+ export interface PutCopyDeskPagesPageIdDraftRequest { reading_hash: string; lines: unknown[] }
485
+ export interface PutCopyDeskPagesPageIdDraftResponse { ok: boolean; outcome: unknown; page_id: unknown; round: unknown; draft: unknown; counter: unknown }
484
486
  export interface PutGovernmentRanksRankKeyPermissionsPermissionKeyResponse { ok: boolean; rank_key: unknown; permission_key: unknown; granted: unknown }
485
487
  export interface PutMingleOptInRequest { opted_in: boolean }
486
488
  export interface PutMingleOptInResponse { opted_in: unknown; updated_at: unknown }
@@ -760,6 +762,8 @@ export interface BongosClient {
760
762
  postCopyDeskFlags(args: RequestArgs & { body: PostCopyDeskFlagsRequest }): Promise<PostCopyDeskFlagsResponse>;
761
763
  /** POST /copy-desk/flags/{id}/close — rank: any-builder */
762
764
  postCopyDeskFlagsIdClose(args: RequestArgs & { body: PostCopyDeskFlagsIdCloseRequest }): Promise<PostCopyDeskFlagsIdCloseResponse>;
765
+ /** GET /copy-desk/next — rank: any-builder */
766
+ getCopyDeskNext(args?: RequestArgs): Promise<ApiResponse>;
763
767
  /** GET /copy-desk/pages — rank: any-builder */
764
768
  getCopyDeskPages(args?: RequestArgs): Promise<ApiResponse>;
765
769
  /** GET /copy-desk/pages/{pageId} — rank: any-builder */
@@ -768,6 +772,10 @@ export interface BongosClient {
768
772
  postCopyDeskPagesPageIdAsks(args: RequestArgs & { body: PostCopyDeskPagesPageIdAsksRequest }): Promise<ApiResponse>;
769
773
  /** POST /copy-desk/pages/{pageId}/claim — rank: any-builder */
770
774
  postCopyDeskPagesPageIdClaim(args?: RequestArgs): Promise<ApiResponse>;
775
+ /** PUT /copy-desk/pages/{pageId}/draft — rank: any-builder */
776
+ putCopyDeskPagesPageIdDraft(args: RequestArgs & { body: PutCopyDeskPagesPageIdDraftRequest }): Promise<PutCopyDeskPagesPageIdDraftResponse>;
777
+ /** POST /copy-desk/pages/{pageId}/submit — rank: any-builder */
778
+ postCopyDeskPagesPageIdSubmit(args?: RequestArgs): Promise<ApiResponse>;
771
779
  /** POST /copy-desk/proposals — rank: any-builder */
772
780
  postCopyDeskProposals(args: RequestArgs & { body: PostCopyDeskProposalsRequest }): Promise<PostCopyDeskProposalsResponse>;
773
781
  /** GET /copy-desk/queue — rank: any-builder */
@@ -339,6 +339,8 @@ export function createClient(opts = {}) {
339
339
  postCopyDeskFlags: (args) => request("POST", "/copy-desk/flags", { hasBody: true }, args),
340
340
  // POST /copy-desk/flags/{id}/close — rank: any-builder — POST /copy-desk/flags/:id/close
341
341
  postCopyDeskFlagsIdClose: (args) => request("POST", "/copy-desk/flags/{id}/close", { hasBody: true }, args),
342
+ // GET /copy-desk/next — rank: any-builder — GET /copy-desk/next
343
+ getCopyDeskNext: (args) => request("GET", "/copy-desk/next", { hasBody: false }, args),
342
344
  // GET /copy-desk/pages — rank: any-builder — GET /copy-desk/pages
343
345
  getCopyDeskPages: (args) => request("GET", "/copy-desk/pages", { hasBody: false }, args),
344
346
  // GET /copy-desk/pages/{pageId} — rank: any-builder — GET /copy-desk/pages/:pageId
@@ -347,6 +349,10 @@ export function createClient(opts = {}) {
347
349
  postCopyDeskPagesPageIdAsks: (args) => request("POST", "/copy-desk/pages/{pageId}/asks", { hasBody: true }, args),
348
350
  // POST /copy-desk/pages/{pageId}/claim — rank: any-builder — POST /copy-desk/pages/:pageId/claim
349
351
  postCopyDeskPagesPageIdClaim: (args) => request("POST", "/copy-desk/pages/{pageId}/claim", { hasBody: true }, args),
352
+ // PUT /copy-desk/pages/{pageId}/draft — rank: any-builder — PUT /copy-desk/pages/:pageId/draft
353
+ putCopyDeskPagesPageIdDraft: (args) => request("PUT", "/copy-desk/pages/{pageId}/draft", { hasBody: true }, args),
354
+ // POST /copy-desk/pages/{pageId}/submit — rank: any-builder — POST /copy-desk/pages/:pageId/submit
355
+ postCopyDeskPagesPageIdSubmit: (args) => request("POST", "/copy-desk/pages/{pageId}/submit", { hasBody: true }, args),
350
356
  // POST /copy-desk/proposals — rank: any-builder — POST /copy-desk/proposals
351
357
  postCopyDeskProposals: (args) => request("POST", "/copy-desk/proposals", { hasBody: true }, args),
352
358
  // GET /copy-desk/queue — rank: any-builder — GET /copy-desk/queue
@@ -5091,6 +5091,37 @@
5091
5091
  ]
5092
5092
  }
5093
5093
  },
5094
+ "/copy-desk/next": {
5095
+ "get": {
5096
+ "operationId": "get_copy_desk_next",
5097
+ "tags": [
5098
+ "copy-desk"
5099
+ ],
5100
+ "summary": "GET /copy-desk/next",
5101
+ "description": "------------------------------------------------------------------------- GET /copy-desk/next — the Tweak/CopyWrite Flow's recommendation (task 1004318 / BV2.TW07, ADR 0341 D8): the page the caller should tweak next and why (\"2 people asked for it\"), plus the next few for \"pick another\". Order: asked for (most distinct askers, then the oldest ask), then changed since the last tweak (most changed lines), then untweaked (landing, builders, status, then inventory order); tweaked pages with no drift last. A page another builder holds, or whose round is in flight, is never recommended (it is listed in `skipped`). The caller's own held page is `resume`, not a recommendation. \"Take next\" is POST /copy-desk/pages/:pageId/claim on `recommended.page_id` (each candidate carries its `take`), one call. The availability rule here is the claim's own, so that call is not refused for a reason this read knew. rank: any signed-in builder. The read is the caller's own and needs no craft; the claim it points at is where the artist gate lives. -------------------------------------------------------------------------\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5102
+ "x-rank": "any-builder",
5103
+ "x-source": "modules/copy-desk/routes/copy-desk.js",
5104
+ "responses": {
5105
+ "200": {
5106
+ "description": "Success."
5107
+ },
5108
+ "400": {
5109
+ "$ref": "#/components/responses/BadRequest"
5110
+ },
5111
+ "401": {
5112
+ "$ref": "#/components/responses/Unauthorized"
5113
+ },
5114
+ "403": {
5115
+ "$ref": "#/components/responses/Forbidden"
5116
+ }
5117
+ },
5118
+ "security": [
5119
+ {
5120
+ "builderSession": []
5121
+ }
5122
+ ]
5123
+ }
5124
+ },
5094
5125
  "/copy-desk/pages": {
5095
5126
  "get": {
5096
5127
  "operationId": "get_copy_desk_pages",
@@ -5280,6 +5311,126 @@
5280
5311
  ]
5281
5312
  }
5282
5313
  },
5314
+ "/copy-desk/pages/{pageId}/draft": {
5315
+ "put": {
5316
+ "operationId": "put_copy_desk_pages_pageId_draft",
5317
+ "tags": [
5318
+ "copy-desk"
5319
+ ],
5320
+ "summary": "PUT /copy-desk/pages/:pageId/draft",
5321
+ "description": "------------------------------------------------------------------------- PUT /copy-desk/pages/:pageId/draft — autosave the artist's draft (task 1004319 / BV2.TW08, ADR 0341 D4). Body: { reading_hash, lines: [{ key, after }] }, the WHOLE draft: every line the artist has changed. The saved draft becomes exactly that (a line sent back at its current text is dropped, so only changed lines are stored). rank: any signed-in builder; only the HOLDER of the page's writing claim (the web claim the page claim took) may save, checked in the lifecycle transaction. Every target is resolved from the page reading by key: section, current text (`before`) and placement are the reading's, never the body's. A body built on an older reading is refused `reading_moved`, whole, since its keys may now mean other lines. Cheap and idempotent: a save that resolves to the draft already stored writes nothing (200 `unchanged`; `updated_at` does not move). The editor debounces; the server only has to make a repeated save free. 200 saved | unchanged with the draft and \"N of M rewritten\" 409 page_not_held the caller does not hold the page (holder named) 409 no_open_round the page has no round: claim it first 409 reading_moved · 400 unknown_line / line_empty / line_too_long -------------------------------------------------------------------------\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5322
+ "x-rank": "any-builder",
5323
+ "x-source": "modules/copy-desk/routes/copy-desk.js",
5324
+ "parameters": [
5325
+ {
5326
+ "name": "pageId",
5327
+ "in": "path",
5328
+ "required": true,
5329
+ "schema": {
5330
+ "type": "string"
5331
+ },
5332
+ "description": "Path parameter `pageId`."
5333
+ }
5334
+ ],
5335
+ "requestBody": {
5336
+ "required": true,
5337
+ "content": {
5338
+ "application/json": {
5339
+ "schema": {
5340
+ "$ref": "#/components/schemas/PutCopyDeskPagesPageIdDraftRequest"
5341
+ }
5342
+ }
5343
+ },
5344
+ "x-validated": true
5345
+ },
5346
+ "responses": {
5347
+ "200": {
5348
+ "description": "Success.",
5349
+ "content": {
5350
+ "application/json": {
5351
+ "schema": {
5352
+ "$ref": "#/components/schemas/PutCopyDeskPagesPageIdDraftResponse"
5353
+ }
5354
+ }
5355
+ }
5356
+ },
5357
+ "400": {
5358
+ "$ref": "#/components/responses/ValidationFailed"
5359
+ },
5360
+ "401": {
5361
+ "$ref": "#/components/responses/Unauthorized"
5362
+ },
5363
+ "403": {
5364
+ "$ref": "#/components/responses/Forbidden"
5365
+ },
5366
+ "404": {
5367
+ "$ref": "#/components/responses/NotFound"
5368
+ }
5369
+ },
5370
+ "security": [
5371
+ {
5372
+ "builderSession": []
5373
+ }
5374
+ ]
5375
+ }
5376
+ },
5377
+ "/copy-desk/pages/{pageId}/submit": {
5378
+ "post": {
5379
+ "operationId": "post_copy_desk_pages_pageId_submit",
5380
+ "tags": [
5381
+ "copy-desk"
5382
+ ],
5383
+ "summary": "POST /copy-desk/pages/:pageId/submit",
5384
+ "description": "------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/submit — freeze the draft and queue the page for /tweak (task 1004319 / BV2.TW08, ADR 0341 D4, D7). Body: {} (it freezes the draft already on the task; nothing is taken from the request). rank: any signed-in builder; the holder only. One lifecycle transaction: * every draft line is re-resolved on the CURRENT page reading; a line the page no longer shows is refused by name (target_gone), as are an ambiguous one and a {…} hole added or dropped. Any refusal refuses the submit, listing the lines, and nothing is frozen; * a rewrite of an UNPLACED line (and of shared shell text with no registry row) leaves the batch and files its own engineer task (source page-tweak-unplaced, backlog), carrying the page, the line and the wording. The page does not wait for it; * the rest is frozen into the `page-tweak` block with each line's file, line and string id from the reading, naming the engineer tasks; * the artist's web claim is released and the task goes back to `ready`: the round reads `submitted`, the /tweak queue. 200 submitted with the batch, the engineer tasks, and where \"next up\" reads (GET /copy-desk/next) 200 already_submitted a repeated submit by the round's artist 409 lines_refused · nothing_to_submit · page_not_held · no_open_round -------------------------------------------------------------------------\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5385
+ "x-rank": "any-builder",
5386
+ "x-source": "modules/copy-desk/routes/copy-desk.js",
5387
+ "parameters": [
5388
+ {
5389
+ "name": "pageId",
5390
+ "in": "path",
5391
+ "required": true,
5392
+ "schema": {
5393
+ "type": "string"
5394
+ },
5395
+ "description": "Path parameter `pageId`."
5396
+ }
5397
+ ],
5398
+ "requestBody": {
5399
+ "required": false,
5400
+ "content": {
5401
+ "application/json": {
5402
+ "schema": {
5403
+ "type": "object",
5404
+ "additionalProperties": true
5405
+ }
5406
+ }
5407
+ },
5408
+ "x-validated": true
5409
+ },
5410
+ "responses": {
5411
+ "200": {
5412
+ "description": "Success."
5413
+ },
5414
+ "400": {
5415
+ "$ref": "#/components/responses/ValidationFailed"
5416
+ },
5417
+ "401": {
5418
+ "$ref": "#/components/responses/Unauthorized"
5419
+ },
5420
+ "403": {
5421
+ "$ref": "#/components/responses/Forbidden"
5422
+ },
5423
+ "404": {
5424
+ "$ref": "#/components/responses/NotFound"
5425
+ }
5426
+ },
5427
+ "security": [
5428
+ {
5429
+ "builderSession": []
5430
+ }
5431
+ ]
5432
+ }
5433
+ },
5283
5434
  "/copy-desk/proposals": {
5284
5435
  "post": {
5285
5436
  "operationId": "post_copy_desk_proposals",
@@ -28151,6 +28302,45 @@
28151
28302
  "criteria"
28152
28303
  ]
28153
28304
  },
28305
+ "PutCopyDeskPagesPageIdDraftRequest": {
28306
+ "type": "object",
28307
+ "properties": {
28308
+ "reading_hash": {
28309
+ "type": "string",
28310
+ "minLength": 1,
28311
+ "maxLength": 64
28312
+ },
28313
+ "lines": {
28314
+ "type": "array"
28315
+ }
28316
+ },
28317
+ "required": [
28318
+ "reading_hash",
28319
+ "lines"
28320
+ ],
28321
+ "additionalProperties": false
28322
+ },
28323
+ "PutCopyDeskPagesPageIdDraftResponse": {
28324
+ "type": "object",
28325
+ "properties": {
28326
+ "ok": {
28327
+ "type": "boolean"
28328
+ },
28329
+ "outcome": {},
28330
+ "page_id": {},
28331
+ "round": {},
28332
+ "draft": {},
28333
+ "counter": {}
28334
+ },
28335
+ "required": [
28336
+ "ok",
28337
+ "outcome",
28338
+ "page_id",
28339
+ "round",
28340
+ "draft",
28341
+ "counter"
28342
+ ]
28343
+ },
28154
28344
  "PutGovernmentRanksRankKeyPermissionsPermissionKeyResponse": {
28155
28345
  "type": "object",
28156
28346
  "properties": {
@@ -28354,9 +28544,9 @@
28354
28544
  "description": "A required dependency/feature is not configured or is temporarily down."
28355
28545
  }
28356
28546
  },
28357
- "x-endpoint-count": 448,
28358
- "x-schema-count": 484,
28547
+ "x-endpoint-count": 451,
28548
+ "x-schema-count": 486,
28359
28549
  "x-undocumented-bodies": 9,
28360
- "x-response-schemas": 331,
28550
+ "x-response-schemas": 332,
28361
28551
  "x-generated-by": "scripts/gds/gen-api-docs.js"
28362
28552
  }
@@ -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. 448 endpoints across 76 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 451 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,16 +210,19 @@ 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` (10)
213
+ ## `copy-desk` (13)
214
214
 
215
215
  | Method | Path | Rank | Body | Description |
216
216
  |---|---|---|---|---|
217
217
  | POST | `/api/bongos/copy-desk/flags` | `any-builder` | `scope`, `surface`, `string_id`, `reason`, `kind` | ------------------------------------------------------------------------- POST /copy-desk/flags — file a flag. |
218
218
  | 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
+ | GET | `/api/bongos/copy-desk/next` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/next — the Tweak/CopyWrite Flow's recommendation… |
219
220
  | GET | `/api/bongos/copy-desk/pages` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/pages — every page's status, count and drift, pl… |
220
221
  | GET | `/api/bongos/copy-desk/pages/:pageId` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/pages/:pageId — one page: status, changelog, the… |
221
222
  | POST | `/api/bongos/copy-desk/pages/:pageId/asks` | `any-builder` | `reason` | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/asks — ask for a page (task 10043… |
222
223
  | POST | `/api/bongos/copy-desk/pages/:pageId/claim` | `any-builder` | validated | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/claim — claim a page's tweak (tas… |
224
+ | PUT | `/api/bongos/copy-desk/pages/:pageId/draft` | `any-builder` | `reading_hash`, `lines` | ------------------------------------------------------------------------- PUT /copy-desk/pages/:pageId/draft — autosave the artist's draf… |
225
+ | POST | `/api/bongos/copy-desk/pages/:pageId/submit` | `any-builder` | validated | ------------------------------------------------------------------------- POST /copy-desk/pages/:pageId/submit — freeze the draft and que… |
223
226
  | 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… |
224
227
  | GET | `/api/bongos/copy-desk/queue` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/queue — the artist's working list. |
225
228
  | GET | `/api/bongos/copy-desk/strings` | `any-builder` | — | ------------------------------------------------------------------------- GET /copy-desk/strings — search the inventory, to find somethin… |
@@ -2605,5 +2605,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
2605
2605
  landed since 1.19.1057 with no explicit bump. run 36390971623. (task 1002620)
2606
2606
  1.19.1059 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2607
2607
  landed since 1.19.1058 with no explicit bump. run 36415558760. (task 1002620)
2608
+ 1.19.1060 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2609
+ landed since 1.19.1059 with no explicit bump. run 36418832327. (task 1002620)
2610
+ 1.19.1061 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2611
+ landed since 1.19.1060 with no explicit bump. run 36423029975. (task 1002620)
2608
2612
  ---------------------------------------------------------------------------
2609
2613
  ```
@@ -297,6 +297,19 @@ async function countPageAskers(pageId) {
297
297
  return rows[0] ? Number(rows[0].askers) : 0;
298
298
  }
299
299
 
300
+ // The recommendation's signal (TW07, ADR 0341 D8): every page with an open
301
+ // ask, its distinct askers and its OLDEST open ask (the tie-break). One grouped
302
+ // read over copy_desk_flags_page_open_idx, never a count per page.
303
+ async function pageAskSummary() {
304
+ const { rows } = await pool.query(
305
+ `SELECT page_id, COUNT(DISTINCT flagged_by)::int AS askers, MIN(flagged_at) AS oldest_ask_at
306
+ FROM copy_desk_flags
307
+ WHERE scope = 'page' AND status = 'open'
308
+ GROUP BY page_id`
309
+ );
310
+ return rows.map((r) => ({ page_id: r.page_id, askers: Number(r.askers) || 0, oldest_ask_at: r.oldest_ask_at }));
311
+ }
312
+
300
313
  // An open ask is RESOLVED when the page's next tweak ships (ADR 0341 D6): every
301
314
  // ask on the page filed before that ship, stamped with the tweak task. Guarded on
302
315
  // status = 'open', so a re-run changes nothing and a dismissed ask stays dismissed.
@@ -316,5 +329,5 @@ module.exports = {
316
329
  SCOPES, FLAG_SCOPES, PAGE_SCOPE, STATUSES, KINDS, CLOSING_STATUSES, MIN_REASON_CHARS, MAX_REASON_CHARS, MAX_NOTE_CHARS,
317
330
  tidy, normalizeFlagPayload, normalizeResolution, normalizePageAsk,
318
331
  insertFlag, listFlags, getFlag, closeFlag,
319
- findOpenPageAsk, countPageAskers, resolvePageAsks,
332
+ findOpenPageAsk, countPageAskers, pageAskSummary, resolvePageAsks,
320
333
  };