@bongos/core 1.19.286 → 1.19.287

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.286",
6
- "core_contract": "1.19.286",
7
- "source_commit": "340b919c505ff5fc5c7701cff26cc21dc237aa65",
5
+ "core_version": "1.19.287",
6
+ "core_contract": "1.19.287",
7
+ "source_commit": "0e9c40ea9f9cbd3b8d38d4b84d2cbca469e939e2",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-21T22:36:56.458Z",
9
+ "built_at": "2026-08-22T00:14:41.365Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 319,
13
13
  "agent_docs_stubbed": 22,
14
- "functional_verbatim": 1383,
14
+ "functional_verbatim": 1385,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1724,
20
- "tree_sha256": "b9e4aeff64c00012240dbc9966201e7e8d6d1068ce7a1c91e7112d9234c5c305",
19
+ "file_count": 1726,
20
+ "tree_sha256": "fc0bf7930e91aebc3ad1c590e667763ca5008d9a2d5edbc91957ae352762443d",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -347,12 +347,12 @@
347
347
  {
348
348
  "path": "clients/bongos-client/README.md",
349
349
  "mode": "0000644",
350
- "sha256": "28ea93104b710162845534c03881affa2ebfa5e9e622c195ef5332fb919762c4"
350
+ "sha256": "75389c8fbcfeb39ce0320d182ea25cc97d2292814743521f834bd98de0ff83da"
351
351
  },
352
352
  {
353
353
  "path": "clients/bongos-client/bongos-client.global.js",
354
354
  "mode": "0000644",
355
- "sha256": "8b6c0691763e21272008f0cb5c24e40d7bc65b297d81e4d1c1b2f58d5f1ab657"
355
+ "sha256": "f008fd2b92e818e1734bbbd4388af483730050780d14822daf16ca5e05110401"
356
356
  },
357
357
  {
358
358
  "path": "clients/bongos-client/examples/hello-world.mjs",
@@ -362,17 +362,17 @@
362
362
  {
363
363
  "path": "clients/bongos-client/index.cjs",
364
364
  "mode": "0000644",
365
- "sha256": "3b7b24b5ced8eead07e1d758e4c1b59321b0fb0f2108aefefd0e4b73bb7cc78b"
365
+ "sha256": "ac7eba0af25322341547f46f9daa385bd557e52c1f580d4873a5d4b35a633ca7"
366
366
  },
367
367
  {
368
368
  "path": "clients/bongos-client/index.d.ts",
369
369
  "mode": "0000644",
370
- "sha256": "183d88c492aae87e1a06a1cb69ba5227db6b023057676637025fee0a77bddd88"
370
+ "sha256": "6d151ca60431e5346007c1939f10f711111c7b7a38f9914be7c8a6ff12d6a75d"
371
371
  },
372
372
  {
373
373
  "path": "clients/bongos-client/index.mjs",
374
374
  "mode": "0000644",
375
- "sha256": "0348faad8b08aefdc42d7bdff79a97a94f547f824c3ec37ed7642cde357a6950"
375
+ "sha256": "60a6ec5d2b7a41e8727769953bd5b38a6746e2373cd8a271ee7b0ba750b84f34"
376
376
  },
377
377
  {
378
378
  "path": "clients/bongos-client/package.json",
@@ -1402,12 +1402,12 @@
1402
1402
  {
1403
1403
  "path": "docs/api-reference.md",
1404
1404
  "mode": "0000644",
1405
- "sha256": "1f499b7f98aba5e51d30f7e3a76c00a3c1b535fe676eb03a31f1eb559d9a0f13"
1405
+ "sha256": "ae992fbebcc171bbc4e669a45f01d3a5dd840bcaad334262136a2060fc362a43"
1406
1406
  },
1407
1407
  {
1408
1408
  "path": "docs/api/openapi.json",
1409
1409
  "mode": "0000644",
1410
- "sha256": "7fa333bb7864fa72672b463f5c53ae9340bd5ecad808bbfe193e835e57ae3e8d"
1410
+ "sha256": "55c2cbd3c8473ed041d0df0c6d9eebe16ed3d333afae9f7dbe3b0ef1a211b4c6"
1411
1411
  },
1412
1412
  {
1413
1413
  "path": "docs/architecture.md",
@@ -3692,7 +3692,7 @@
3692
3692
  {
3693
3693
  "path": "modules/ideas/inbox.js",
3694
3694
  "mode": "0000644",
3695
- "sha256": "379a6e51a8865dcf52061d858e7e2f3b572f16bc04473aba163e52cadcaf1873"
3695
+ "sha256": "19af72245517260ac6ee670c93fa3cda99a678da25a7fa6a5d6ec565995201ce"
3696
3696
  },
3697
3697
  {
3698
3698
  "path": "modules/ideas/migrations/ideas_001_grades.sql",
@@ -3727,7 +3727,7 @@
3727
3727
  {
3728
3728
  "path": "modules/ideas/routes/inbox.js",
3729
3729
  "mode": "0000644",
3730
- "sha256": "9c7027f70daba8cb956ab540567972afcec96900ce8d7f7793647bc58c13abdd"
3730
+ "sha256": "47c2a3beb6bed3b206ec36344950fe115189debf75a38cf202bfafaa5dbb2adb"
3731
3731
  },
3732
3732
  {
3733
3733
  "path": "modules/ideas/routing.js",
@@ -3804,6 +3804,11 @@
3804
3804
  "mode": "0000644",
3805
3805
  "sha256": "ff30d2749a0f6b17beb776be2d862967cdea2ad03488e7ab499d2f9d093e8805"
3806
3806
  },
3807
+ {
3808
+ "path": "modules/lifecycle/goal-edits.js",
3809
+ "mode": "0000644",
3810
+ "sha256": "0367f88aefa890d8d7f2472dd847467d632150a93db8a96b85717b5fb1cc8c9e"
3811
+ },
3807
3812
  {
3808
3813
  "path": "modules/lifecycle/hierarchy.js",
3809
3814
  "mode": "0000644",
@@ -3862,7 +3867,7 @@
3862
3867
  {
3863
3868
  "path": "modules/lifecycle/routes/done-when.js",
3864
3869
  "mode": "0000644",
3865
- "sha256": "c81e1474e237dfa2e3be5f80df56344cf7f9ca50dc7b84e45b2fec64509b900f"
3870
+ "sha256": "7fb4a74237c1f84a5c20591663e634a7b190861e6a3f1c5804e22145ef58f6be"
3866
3871
  },
3867
3872
  {
3868
3873
  "path": "modules/lifecycle/routes/gate-approvals.js",
@@ -3872,7 +3877,7 @@
3872
3877
  {
3873
3878
  "path": "modules/lifecycle/routes/goals.js",
3874
3879
  "mode": "0000644",
3875
- "sha256": "a986f861d919aec81e58683782ceae902e8590cb581710842113a04439984c16"
3880
+ "sha256": "a94284db44e4108b21ff3a5f60ac25c0b16ff4330839f9d37045e90e763d430e"
3876
3881
  },
3877
3882
  {
3878
3883
  "path": "modules/lifecycle/routes/lifecycle.js",
@@ -4507,12 +4512,12 @@
4507
4512
  {
4508
4513
  "path": "package-lock.json",
4509
4514
  "mode": "0000644",
4510
- "sha256": "ade48bed2ae2a0e3019f7937eefa6eff80495f6bb0fa7de7cda033b7e6acee2c"
4515
+ "sha256": "ceaff2d7728751d980cf1e01c3342de37baa727b682bb70a75792f9825752851"
4511
4516
  },
4512
4517
  {
4513
4518
  "path": "package.json",
4514
4519
  "mode": "0000644",
4515
- "sha256": "7eb6abceda41293042967ce827a4fa252646a35b45e60bae9ba1a6a348d320a1"
4520
+ "sha256": "d2d685a112ab41f0698b9fc2436ff0e534bbc3441de3a0ef9c3e1821a92ba37d"
4516
4521
  },
4517
4522
  {
4518
4523
  "path": "public-docs/index.html",
@@ -6022,7 +6027,7 @@
6022
6027
  {
6023
6028
  "path": "src/bongos/route-rank-check.js",
6024
6029
  "mode": "0000644",
6025
- "sha256": "93b2a09220f4d96f69294531cbca274b1132d164cf32be2f66d40d30e1953551"
6030
+ "sha256": "be8bc6ecd3ab1dbec4d3224d684b64d100920ad2cf7d08c51898160fefdaf534"
6026
6031
  },
6027
6032
  {
6028
6033
  "path": "src/bongos/routes.js",
@@ -6157,7 +6162,7 @@
6157
6162
  {
6158
6163
  "path": "src/module-api.js",
6159
6164
  "mode": "0000644",
6160
- "sha256": "32e103cd07c81ccc0a2137ef31b3824e5085a93ebf95f9cca7c107d58b25da3c"
6165
+ "sha256": "4d7fa01bf03ea2b91130272d141e16ac4f11aca831b7e6df8fb54eea7ccc8c1f"
6161
6166
  },
6162
6167
  {
6163
6168
  "path": "src/module-loader/catalog.js",
@@ -7939,6 +7944,11 @@
7939
7944
  "mode": "0000644",
7940
7945
  "sha256": "211aa868b86a2b663f5525c3d2ddfa406498d608363d28c0786219d3c0b6e249"
7941
7946
  },
7947
+ {
7948
+ "path": "tests/prose_edits.mjs",
7949
+ "mode": "0000644",
7950
+ "sha256": "d5918a7f47e989355e2b78083710736278c6d5f75c13ac8434d5ad6fac6a3d03"
7951
+ },
7942
7952
  {
7943
7953
  "path": "tests/provision.mjs",
7944
7954
  "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
- - 290 operations across 47 resource groups
8
+ - 293 operations across 47 resource groups
9
9
 
10
10
  ## Install
11
11
 
@@ -279,6 +279,8 @@ function createClient(opts = {}) {
279
279
  postDiscordChannelsReconcile: (args) => request("POST", "/discord/channels/reconcile", { hasBody: true }, args),
280
280
  },
281
281
  "doneWhen": {
282
+ // PATCH /done-when/{criterionId} — rank: metic+archon — PATCH /done-when/:criterionId
283
+ patchDoneWhenCriterionId: (args) => request("PATCH", "/done-when/{criterionId}", { hasBody: true }, args),
282
284
  // POST /done-when/{criterionId}/satisfy — rank: metic+archon — POST /done-when/:criterionId/satisfy
283
285
  postDoneWhenCriterionIdSatisfy: (args) => request("POST", "/done-when/{criterionId}/satisfy", { hasBody: true }, args),
284
286
  // POST /done-when/{criterionId}/unsatisfy — rank: metic+archon — POST /done-when/:criterionId/unsatisfy
@@ -309,6 +311,8 @@ function createClient(opts = {}) {
309
311
  postGoals: (args) => request("POST", "/goals", { hasBody: true }, args),
310
312
  // GET /goals/{id} — rank: any-builder — GET /goals/:id
311
313
  getGoalsId: (args) => request("GET", "/goals/{id}", { hasBody: false }, args),
314
+ // PATCH /goals/{id} — rank: any-builder — PATCH /goals/:id
315
+ patchGoalsId: (args) => request("PATCH", "/goals/{id}", { hasBody: true }, args),
312
316
  // POST /goals/{id}/archive — rank: metic+archon — POST /goals/:id/archive
313
317
  postGoalsIdArchive: (args) => request("POST", "/goals/{id}/archive", { hasBody: true }, args),
314
318
  // GET /goals/{id}/conflicts — rank: any-builder — GET /goals/:id/conflicts
@@ -397,6 +401,8 @@ function createClient(opts = {}) {
397
401
  getInboxId: (args) => request("GET", "/inbox/{id}", { hasBody: false }, args),
398
402
  // PATCH /inbox/{id} — rank: metic+archon — PATCH /inbox/:id
399
403
  patchInboxId: (args) => request("PATCH", "/inbox/{id}", { hasBody: true }, args),
404
+ // PATCH /inbox/{id}/body — rank: any-builder — PATCH /inbox/:id/body
405
+ patchInboxIdBody: (args) => request("PATCH", "/inbox/{id}/body", { hasBody: true }, args),
400
406
  // POST /inbox/{id}/ratify — rank: metic+archon — POST /inbox/:id/ratify
401
407
  postInboxIdRatify: (args) => request("POST", "/inbox/{id}/ratify", { hasBody: true }, args),
402
408
  // POST /inbox/{id}/resubmit — rank: any-builder — POST /inbox/:id/resubmit
@@ -278,6 +278,8 @@ function createClient(opts = {}) {
278
278
  postDiscordChannelsReconcile: (args) => request("POST", "/discord/channels/reconcile", { hasBody: true }, args),
279
279
  },
280
280
  "doneWhen": {
281
+ // PATCH /done-when/{criterionId} — rank: metic+archon — PATCH /done-when/:criterionId
282
+ patchDoneWhenCriterionId: (args) => request("PATCH", "/done-when/{criterionId}", { hasBody: true }, args),
281
283
  // POST /done-when/{criterionId}/satisfy — rank: metic+archon — POST /done-when/:criterionId/satisfy
282
284
  postDoneWhenCriterionIdSatisfy: (args) => request("POST", "/done-when/{criterionId}/satisfy", { hasBody: true }, args),
283
285
  // POST /done-when/{criterionId}/unsatisfy — rank: metic+archon — POST /done-when/:criterionId/unsatisfy
@@ -308,6 +310,8 @@ function createClient(opts = {}) {
308
310
  postGoals: (args) => request("POST", "/goals", { hasBody: true }, args),
309
311
  // GET /goals/{id} — rank: any-builder — GET /goals/:id
310
312
  getGoalsId: (args) => request("GET", "/goals/{id}", { hasBody: false }, args),
313
+ // PATCH /goals/{id} — rank: any-builder — PATCH /goals/:id
314
+ patchGoalsId: (args) => request("PATCH", "/goals/{id}", { hasBody: true }, args),
311
315
  // POST /goals/{id}/archive — rank: metic+archon — POST /goals/:id/archive
312
316
  postGoalsIdArchive: (args) => request("POST", "/goals/{id}/archive", { hasBody: true }, args),
313
317
  // GET /goals/{id}/conflicts — rank: any-builder — GET /goals/:id/conflicts
@@ -396,6 +400,8 @@ function createClient(opts = {}) {
396
400
  getInboxId: (args) => request("GET", "/inbox/{id}", { hasBody: false }, args),
397
401
  // PATCH /inbox/{id} — rank: metic+archon — PATCH /inbox/:id
398
402
  patchInboxId: (args) => request("PATCH", "/inbox/{id}", { hasBody: true }, args),
403
+ // PATCH /inbox/{id}/body — rank: any-builder — PATCH /inbox/:id/body
404
+ patchInboxIdBody: (args) => request("PATCH", "/inbox/{id}/body", { hasBody: true }, args),
399
405
  // POST /inbox/{id}/ratify — rank: metic+archon — POST /inbox/:id/ratify
400
406
  postInboxIdRatify: (args) => request("POST", "/inbox/{id}/ratify", { hasBody: true }, args),
401
407
  // POST /inbox/{id}/resubmit — rank: any-builder — POST /inbox/:id/resubmit
@@ -123,10 +123,12 @@ export interface PatchBuildersIdBudgetResponse { builder: unknown }
123
123
  export interface PatchBuildersIdRankRequest { rank: string }
124
124
  export interface PatchBuildersIdRankResponse { builder: unknown; previous_rank: unknown; direction: unknown; credit_delta: unknown; broadcast: unknown }
125
125
  export interface PatchBuildersIdStatusRequest { status: "active" | "inactive"; reason?: string }
126
+ export interface PatchDoneWhenCriterionIdRequest { criterion_md: string }
127
+ export interface PatchDoneWhenCriterionIdResponse { ok: boolean; criterion: unknown; deltas: unknown; unchanged: boolean }
126
128
  export interface PatchGoalsIdMembersBuilderIdRequest { membership_kind: string }
127
129
  export interface PatchGoalsIdMembersBuilderIdResponse { ok: boolean; member: unknown; changed: boolean }
128
- export interface PatchGoalsIdVisibilityRequest { visibility: string }
129
- export interface PatchGoalsIdVisibilityResponse { ok: boolean; goal: unknown }
130
+ export interface PatchInboxIdBodyRequest { body_md: string }
131
+ export interface PatchInboxIdBodyResponse { ok: boolean; idea: unknown; delta: unknown; unchanged: unknown }
130
132
  export interface PatchInboxIdRequest { status?: "open" | "promoted" | "discarded" | "merged"; kind?: string; promoted_to_task_id?: number; reviewed_at?: unknown; merged_into_idea_id?: number; triage_note?: string }
131
133
  export interface PatchInboxIdResponse { idea: unknown }
132
134
  export interface PatchMeCrossProjectRequest { hide_stats: boolean }
@@ -538,6 +540,8 @@ export interface BongosClient {
538
540
  postDiscordChannelsReconcile(args?: RequestArgs): Promise<PostDiscordChannelsReconcileResponse>;
539
541
  };
540
542
  "doneWhen": {
543
+ /** PATCH /done-when/{criterionId} — rank: metic+archon */
544
+ patchDoneWhenCriterionId(args: RequestArgs & { body: PatchDoneWhenCriterionIdRequest }): Promise<PatchDoneWhenCriterionIdResponse>;
541
545
  /** POST /done-when/{criterionId}/satisfy — rank: metic+archon */
542
546
  postDoneWhenCriterionIdSatisfy(args?: RequestArgs & { body?: PostDoneWhenCriterionIdSatisfyRequest }): Promise<PostDoneWhenCriterionIdSatisfyResponse>;
543
547
  /** POST /done-when/{criterionId}/unsatisfy — rank: metic+archon */
@@ -568,6 +572,8 @@ export interface BongosClient {
568
572
  postGoals(args: RequestArgs & { body: PostGoalsRequest }): Promise<PostGoalsResponse>;
569
573
  /** GET /goals/{id} — rank: any-builder */
570
574
  getGoalsId(args?: RequestArgs): Promise<GetGoalsIdResponse>;
575
+ /** PATCH /goals/{id} — rank: any-builder */
576
+ patchGoalsId(args?: RequestArgs): Promise<ApiResponse>;
571
577
  /** POST /goals/{id}/archive — rank: metic+archon */
572
578
  postGoalsIdArchive(args?: RequestArgs): Promise<PostGoalsIdArchiveResponse>;
573
579
  /** GET /goals/{id}/conflicts — rank: any-builder */
@@ -605,7 +611,7 @@ export interface BongosClient {
605
611
  /** POST /goals/{id}/transfer — rank: any-builder */
606
612
  postGoalsIdTransfer(args?: RequestArgs & { body?: PostGoalsIdTransferRequest }): Promise<PostGoalsIdTransferResponse>;
607
613
  /** PATCH /goals/{id}/visibility — rank: any-builder */
608
- patchGoalsIdVisibility(args: RequestArgs & { body: PatchGoalsIdVisibilityRequest }): Promise<PatchGoalsIdVisibilityResponse>;
614
+ patchGoalsIdVisibility(args?: RequestArgs): Promise<ApiResponse>;
609
615
  /** GET /goals/inbox — rank: any-builder */
610
616
  getGoalsInbox(args?: RequestArgs): Promise<ApiResponse>;
611
617
  /** POST /goals/reorder — rank: metic+archon */
@@ -656,6 +662,8 @@ export interface BongosClient {
656
662
  getInboxId(args?: RequestArgs): Promise<GetInboxIdResponse>;
657
663
  /** PATCH /inbox/{id} — rank: metic+archon */
658
664
  patchInboxId(args?: RequestArgs & { body?: PatchInboxIdRequest }): Promise<PatchInboxIdResponse>;
665
+ /** PATCH /inbox/{id}/body — rank: any-builder */
666
+ patchInboxIdBody(args: RequestArgs & { body: PatchInboxIdBodyRequest }): Promise<PatchInboxIdBodyResponse>;
659
667
  /** POST /inbox/{id}/ratify — rank: metic+archon */
660
668
  postInboxIdRatify(args?: RequestArgs & { body?: PostInboxIdRatifyRequest }): Promise<ApiResponse>;
661
669
  /** POST /inbox/{id}/resubmit — rank: any-builder */
@@ -275,6 +275,8 @@ export function createClient(opts = {}) {
275
275
  postDiscordChannelsReconcile: (args) => request("POST", "/discord/channels/reconcile", { hasBody: true }, args),
276
276
  },
277
277
  "doneWhen": {
278
+ // PATCH /done-when/{criterionId} — rank: metic+archon — PATCH /done-when/:criterionId
279
+ patchDoneWhenCriterionId: (args) => request("PATCH", "/done-when/{criterionId}", { hasBody: true }, args),
278
280
  // POST /done-when/{criterionId}/satisfy — rank: metic+archon — POST /done-when/:criterionId/satisfy
279
281
  postDoneWhenCriterionIdSatisfy: (args) => request("POST", "/done-when/{criterionId}/satisfy", { hasBody: true }, args),
280
282
  // POST /done-when/{criterionId}/unsatisfy — rank: metic+archon — POST /done-when/:criterionId/unsatisfy
@@ -305,6 +307,8 @@ export function createClient(opts = {}) {
305
307
  postGoals: (args) => request("POST", "/goals", { hasBody: true }, args),
306
308
  // GET /goals/{id} — rank: any-builder — GET /goals/:id
307
309
  getGoalsId: (args) => request("GET", "/goals/{id}", { hasBody: false }, args),
310
+ // PATCH /goals/{id} — rank: any-builder — PATCH /goals/:id
311
+ patchGoalsId: (args) => request("PATCH", "/goals/{id}", { hasBody: true }, args),
308
312
  // POST /goals/{id}/archive — rank: metic+archon — POST /goals/:id/archive
309
313
  postGoalsIdArchive: (args) => request("POST", "/goals/{id}/archive", { hasBody: true }, args),
310
314
  // GET /goals/{id}/conflicts — rank: any-builder — GET /goals/:id/conflicts
@@ -393,6 +397,8 @@ export function createClient(opts = {}) {
393
397
  getInboxId: (args) => request("GET", "/inbox/{id}", { hasBody: false }, args),
394
398
  // PATCH /inbox/{id} — rank: metic+archon — PATCH /inbox/:id
395
399
  patchInboxId: (args) => request("PATCH", "/inbox/{id}", { hasBody: true }, args),
400
+ // PATCH /inbox/{id}/body — rank: any-builder — PATCH /inbox/:id/body
401
+ patchInboxIdBody: (args) => request("PATCH", "/inbox/{id}/body", { hasBody: true }, args),
396
402
  // POST /inbox/{id}/ratify — rank: metic+archon — POST /inbox/:id/ratify
397
403
  postInboxIdRatify: (args) => request("POST", "/inbox/{id}/ratify", { hasBody: true }, args),
398
404
  // POST /inbox/{id}/resubmit — rank: any-builder — POST /inbox/:id/resubmit
@@ -3609,6 +3609,72 @@
3609
3609
  ]
3610
3610
  }
3611
3611
  },
3612
+ "/done-when/{criterionId}": {
3613
+ "patch": {
3614
+ "operationId": "patch_done_when_criterionId",
3615
+ "tags": [
3616
+ "done-when"
3617
+ ],
3618
+ "summary": "PATCH /done-when/:criterionId",
3619
+ "description": "PATCH /done-when/:criterionId — correct a criterion's TEXT (task 1003102). Was write-once: this file exposed create, satisfy and unsatisfy and nothing else, so wrong text had no API repair path. The incident that forced it: a shell-quoting error stripped backtick-wrapped literals out of three criteria on goal 1000073 at CREATION time — the intent was recorded, the text was wrong, and the only channels were prod SQL or archiving the goal (worse: criteria are version-level rows, so an archived goal's criteria linger in the version rollup). A SATISFIED criterion is REFUSED, by name — see prose-edits.criterionProseRefusal for why that is a decision and not a limitation: a satisfied criterion is a claim someone verified, and re-wording it re-points that verification at text nobody checked. Unsatisfy → edit → re-satisfy makes the undo a recorded act. Gated like criterion CREATION — BOTH HALVES. The permission `criterion.create` is only the RANK floor; the sibling POST /versions/:id/done-when also runs authorizeCriterionCreate, the per-goal owner|manager wall (ADR 0154). Copying just the rank half would let any Metic rewrite criteria on a goal they neither own, manage, nor belong to — reusing the SAME pure gate is the only way the claim \"gated like creation\" is true. (Caught by the grader on the first cut of task 1003102: the comment said it, the code did half of it.) rank: metic+archon — matches POST /versions/:id/done-when.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `criterion.create` (all required).",
3620
+ "x-rank": "metic+archon",
3621
+ "x-source": "modules/lifecycle/routes/done-when.js",
3622
+ "x-permissions": [
3623
+ "criterion.create"
3624
+ ],
3625
+ "parameters": [
3626
+ {
3627
+ "name": "criterionId",
3628
+ "in": "path",
3629
+ "required": true,
3630
+ "schema": {
3631
+ "type": "string"
3632
+ },
3633
+ "description": "Path parameter `criterionId`."
3634
+ }
3635
+ ],
3636
+ "requestBody": {
3637
+ "required": true,
3638
+ "content": {
3639
+ "application/json": {
3640
+ "schema": {
3641
+ "$ref": "#/components/schemas/PatchDoneWhenCriterionIdRequest"
3642
+ }
3643
+ }
3644
+ },
3645
+ "x-validated": true
3646
+ },
3647
+ "responses": {
3648
+ "200": {
3649
+ "description": "Success.",
3650
+ "content": {
3651
+ "application/json": {
3652
+ "schema": {
3653
+ "$ref": "#/components/schemas/PatchDoneWhenCriterionIdResponse"
3654
+ }
3655
+ }
3656
+ }
3657
+ },
3658
+ "400": {
3659
+ "$ref": "#/components/responses/ValidationFailed"
3660
+ },
3661
+ "401": {
3662
+ "$ref": "#/components/responses/Unauthorized"
3663
+ },
3664
+ "403": {
3665
+ "$ref": "#/components/responses/Forbidden"
3666
+ },
3667
+ "404": {
3668
+ "$ref": "#/components/responses/NotFound"
3669
+ }
3670
+ },
3671
+ "security": [
3672
+ {
3673
+ "builderSession": []
3674
+ }
3675
+ ]
3676
+ }
3677
+ },
3612
3678
  "/done-when/{criterionId}/satisfy": {
3613
3679
  "post": {
3614
3680
  "operationId": "post_done_when_criterionId_satisfy",
@@ -4212,6 +4278,49 @@
4212
4278
  "builderSession": []
4213
4279
  }
4214
4280
  ]
4281
+ },
4282
+ "patch": {
4283
+ "operationId": "patch_goals_id",
4284
+ "tags": [
4285
+ "goals"
4286
+ ],
4287
+ "summary": "PATCH /goals/:id",
4288
+ "description": "PATCH /goals/:id — correct a goal's own title/description (task 1003102). Handler + rationale + rank note: ../goal-edits.js. Pinned in route-rank-check.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
4289
+ "x-rank": "any-builder",
4290
+ "x-source": "modules/lifecycle/routes/goals.js",
4291
+ "parameters": [
4292
+ {
4293
+ "name": "id",
4294
+ "in": "path",
4295
+ "required": true,
4296
+ "schema": {
4297
+ "type": "string"
4298
+ },
4299
+ "description": "Path parameter `id`."
4300
+ }
4301
+ ],
4302
+ "responses": {
4303
+ "200": {
4304
+ "description": "Success."
4305
+ },
4306
+ "400": {
4307
+ "$ref": "#/components/responses/BadRequest"
4308
+ },
4309
+ "401": {
4310
+ "$ref": "#/components/responses/Unauthorized"
4311
+ },
4312
+ "403": {
4313
+ "$ref": "#/components/responses/Forbidden"
4314
+ },
4315
+ "404": {
4316
+ "$ref": "#/components/responses/NotFound"
4317
+ }
4318
+ },
4319
+ "security": [
4320
+ {
4321
+ "builderSession": []
4322
+ }
4323
+ ]
4215
4324
  }
4216
4325
  },
4217
4326
  "/goals/{id}/archive": {
@@ -5324,30 +5433,12 @@
5324
5433
  "description": "Path parameter `id`."
5325
5434
  }
5326
5435
  ],
5327
- "requestBody": {
5328
- "required": true,
5329
- "content": {
5330
- "application/json": {
5331
- "schema": {
5332
- "$ref": "#/components/schemas/PatchGoalsIdVisibilityRequest"
5333
- }
5334
- }
5335
- },
5336
- "x-validated": true
5337
- },
5338
5436
  "responses": {
5339
5437
  "200": {
5340
- "description": "Success.",
5341
- "content": {
5342
- "application/json": {
5343
- "schema": {
5344
- "$ref": "#/components/schemas/PatchGoalsIdVisibilityResponse"
5345
- }
5346
- }
5347
- }
5438
+ "description": "Success."
5348
5439
  },
5349
5440
  "400": {
5350
- "$ref": "#/components/responses/ValidationFailed"
5441
+ "$ref": "#/components/responses/BadRequest"
5351
5442
  },
5352
5443
  "401": {
5353
5444
  "$ref": "#/components/responses/Unauthorized"
@@ -6249,7 +6340,7 @@
6249
6340
  "inbox"
6250
6341
  ],
6251
6342
  "summary": "PATCH /inbox/:id",
6252
- "description": "Metic+ (task 360 / ADR 0018): idea triage (promote/discard/merge) shapes the backlog. Criterion C2 assigns triage to Metic, so this widened from archon-only to metic+archon when the three-rank model went live. Any builder can still FILE an idea (POST /inbox above); a Xenos cannot triage. rank: metic+archon — idea triage shapes the backlog; criterion C2 / task 360 / ADR 0018.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `idea.triage` (all required).",
6343
+ "description": "**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `idea.triage` (all required).",
6253
6344
  "x-rank": "metic+archon",
6254
6345
  "x-source": "modules/ideas/routes/inbox.js",
6255
6346
  "x-permissions": [
@@ -6308,6 +6399,69 @@
6308
6399
  ]
6309
6400
  }
6310
6401
  },
6402
+ "/inbox/{id}/body": {
6403
+ "patch": {
6404
+ "operationId": "patch_inbox_id_body",
6405
+ "tags": [
6406
+ "inbox"
6407
+ ],
6408
+ "summary": "PATCH /inbox/:id/body",
6409
+ "description": "Metic+ (task 360 / ADR 0018): idea triage (promote/discard/merge) shapes the backlog. Criterion C2 assigns triage to Metic, so this widened from archon-only to metic+archon when the three-rank model went live. Any builder can still FILE an idea (POST /inbox above); a Xenos cannot triage. rank: metic+archon — idea triage shapes the backlog; criterion C2 / task 360 / ADR 0018. PATCH /inbox/:id/body — correct an idea's own TEXT (task 1003102 / idea 1000740). A SEPARATE route rather than a new field on PATCH /inbox/:id, deliberately. That route is gated `requirePermission('idea.triage')`, and the ask here is that an idea's AUTHOR can fix their own words. Adding body_md there would have meant dropping the whole triage route to requireBuilder and re-authorizing every field in-handler — widening a pinned route's classified rank to reach one field. A new route with its own pin widens nothing: triage keeps its gate, and this one carries its own, narrower rule. AUTHOR (idea_inbox.captured_by) or a triager. The author case is the point: fixing your own typo must not require escalating to a Metic. rank: any-builder (requireBuilder) + the in-handler author|triage gate. Pinned in route-rank-check.MODULE_EXPECTED_RANKS['ideas']. asyncHandler (the doorway wrapper) owns the catch + the 500 log, so this route carries no console.error of its own — one central log site instead of a 16th copy of the same two lines in this file.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6410
+ "x-rank": "any-builder",
6411
+ "x-source": "modules/ideas/routes/inbox.js",
6412
+ "parameters": [
6413
+ {
6414
+ "name": "id",
6415
+ "in": "path",
6416
+ "required": true,
6417
+ "schema": {
6418
+ "type": "string"
6419
+ },
6420
+ "description": "Path parameter `id`."
6421
+ }
6422
+ ],
6423
+ "requestBody": {
6424
+ "required": true,
6425
+ "content": {
6426
+ "application/json": {
6427
+ "schema": {
6428
+ "$ref": "#/components/schemas/PatchInboxIdBodyRequest"
6429
+ }
6430
+ }
6431
+ },
6432
+ "x-validated": true
6433
+ },
6434
+ "responses": {
6435
+ "200": {
6436
+ "description": "Success.",
6437
+ "content": {
6438
+ "application/json": {
6439
+ "schema": {
6440
+ "$ref": "#/components/schemas/PatchInboxIdBodyResponse"
6441
+ }
6442
+ }
6443
+ }
6444
+ },
6445
+ "400": {
6446
+ "$ref": "#/components/responses/ValidationFailed"
6447
+ },
6448
+ "401": {
6449
+ "$ref": "#/components/responses/Unauthorized"
6450
+ },
6451
+ "403": {
6452
+ "$ref": "#/components/responses/Forbidden"
6453
+ },
6454
+ "404": {
6455
+ "$ref": "#/components/responses/NotFound"
6456
+ }
6457
+ },
6458
+ "security": [
6459
+ {
6460
+ "builderSession": []
6461
+ }
6462
+ ]
6463
+ }
6464
+ },
6311
6465
  "/inbox/{id}/ratify": {
6312
6466
  "post": {
6313
6467
  "operationId": "post_inbox_id_ratify",
@@ -14674,6 +14828,39 @@
14674
14828
  ],
14675
14829
  "additionalProperties": false
14676
14830
  },
14831
+ "PatchDoneWhenCriterionIdRequest": {
14832
+ "type": "object",
14833
+ "properties": {
14834
+ "criterion_md": {
14835
+ "type": "string",
14836
+ "minLength": 1,
14837
+ "maxLength": 10000
14838
+ }
14839
+ },
14840
+ "required": [
14841
+ "criterion_md"
14842
+ ],
14843
+ "additionalProperties": false
14844
+ },
14845
+ "PatchDoneWhenCriterionIdResponse": {
14846
+ "type": "object",
14847
+ "properties": {
14848
+ "ok": {
14849
+ "type": "boolean"
14850
+ },
14851
+ "criterion": {},
14852
+ "deltas": {},
14853
+ "unchanged": {
14854
+ "type": "boolean"
14855
+ }
14856
+ },
14857
+ "required": [
14858
+ "ok",
14859
+ "criterion",
14860
+ "deltas",
14861
+ "unchanged"
14862
+ ]
14863
+ },
14677
14864
  "PatchGoalsIdMembersBuilderIdRequest": {
14678
14865
  "type": "object",
14679
14866
  "properties": {
@@ -14703,29 +14890,35 @@
14703
14890
  "changed"
14704
14891
  ]
14705
14892
  },
14706
- "PatchGoalsIdVisibilityRequest": {
14893
+ "PatchInboxIdBodyRequest": {
14707
14894
  "type": "object",
14708
14895
  "properties": {
14709
- "visibility": {
14710
- "type": "string"
14896
+ "body_md": {
14897
+ "type": "string",
14898
+ "minLength": 1,
14899
+ "maxLength": 50000
14711
14900
  }
14712
14901
  },
14713
14902
  "required": [
14714
- "visibility"
14903
+ "body_md"
14715
14904
  ],
14716
14905
  "additionalProperties": false
14717
14906
  },
14718
- "PatchGoalsIdVisibilityResponse": {
14907
+ "PatchInboxIdBodyResponse": {
14719
14908
  "type": "object",
14720
14909
  "properties": {
14721
14910
  "ok": {
14722
14911
  "type": "boolean"
14723
14912
  },
14724
- "goal": {}
14913
+ "idea": {},
14914
+ "delta": {},
14915
+ "unchanged": {}
14725
14916
  },
14726
14917
  "required": [
14727
14918
  "ok",
14728
- "goal"
14919
+ "idea",
14920
+ "delta",
14921
+ "unchanged"
14729
14922
  ]
14730
14923
  },
14731
14924
  "PatchInboxIdRequest": {
@@ -18353,9 +18546,9 @@
18353
18546
  "description": "A required dependency/feature is not configured or is temporarily down."
18354
18547
  }
18355
18548
  },
18356
- "x-endpoint-count": 290,
18357
- "x-schema-count": 326,
18549
+ "x-endpoint-count": 293,
18550
+ "x-schema-count": 328,
18358
18551
  "x-undocumented-bodies": 8,
18359
- "x-response-schemas": 218,
18552
+ "x-response-schemas": 219,
18360
18553
  "x-generated-by": "scripts/gds/gen-api-docs.js"
18361
18554
  }