@bongos/core 1.20.58 → 1.20.59

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 (42) hide show
  1. package/.bongos-core.json +80 -40
  2. package/clients/bongos-client/index.d.ts +2 -2
  3. package/docs/api/openapi.json +9 -3
  4. package/docs/api-reference.md +1 -1
  5. package/docs/architecture.md +1 -0
  6. package/docs/copy-inventory.md +1 -1
  7. package/docs/copy-registry.json +9 -9
  8. package/docs/module-api-changelog.md +2 -0
  9. package/docs/page-readings.json +30 -30
  10. package/migrations/core_268_builders_main_discipline.sql +35 -0
  11. package/modules/copy-desk/artist-stats.js +56 -0
  12. package/modules/copy-desk/module.json +1 -1
  13. package/modules/copy-desk/page-status.js +39 -0
  14. package/modules/copy-desk/routes/copy-desk.js +7 -16
  15. package/modules/copy-desk/tests/copy_no_cms.mjs +10 -1
  16. package/modules/economy/credits-by-craft.js +208 -0
  17. package/modules/economy/reward.js +8 -0
  18. package/modules/hall-ui/public/hall-render.js +2 -2
  19. package/modules/hall-ui/public/profile.js +1 -1
  20. package/modules/ideas/ideator-stats.js +149 -0
  21. package/modules/ideas/module.json +2 -1
  22. package/modules/ideas/routes/inbox.js +7 -0
  23. package/modules/lifecycle/activity.js +5 -2
  24. package/modules/lifecycle/db-analytics.js +4 -2
  25. package/modules/lifecycle/db-tasks.js +49 -1
  26. package/modules/lifecycle/db.js +3 -2
  27. package/modules/lifecycle/page-tweak-reads.js +23 -5
  28. package/package-lock.json +2 -2
  29. package/package.json +1 -1
  30. package/release-notes.json +6 -0
  31. package/scripts/gds/run-unit-tests.js +5 -0
  32. package/src/bongos/db.js +44 -6
  33. package/src/bongos/role-stats.js +155 -0
  34. package/src/bongos/routes/builders.js +15 -2
  35. package/src/bongos/routes/me.js +11 -3
  36. package/src/module-api.js +1 -1
  37. package/tests/copy_desk_page_reads.mjs +1 -1
  38. package/tests/fixtures/page-ledger.mjs +1 -1
  39. package/tests/main_discipline.mjs +81 -0
  40. package/tests/profile_role_stats.mjs +416 -0
  41. package/tests/role_stats_db.mjs +237 -0
  42. package/tests/tweak_replaces_artist_review.mjs +1 -1
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.20.58",
6
- "core_contract": "1.20.58",
7
- "source_commit": "51686b250c9118e24398778927083ad1cd0a3335",
5
+ "core_version": "1.20.59",
6
+ "core_contract": "1.20.59",
7
+ "source_commit": "1e24a0934c9535d15896e642111367f8e6505c7c",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-10-01T06:39:29.444Z",
9
+ "built_at": "2026-10-01T07:04:49.482Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 571,
13
13
  "agent_docs_stubbed": 27,
14
- "functional_verbatim": 2762,
14
+ "functional_verbatim": 2770,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 3361,
20
- "tree_sha256": "8c6aa4c50502f2c98ecbdcf08c3fdbe56c82b738296aafcda5f59cb608e9b824",
19
+ "file_count": 3369,
20
+ "tree_sha256": "82f155ef0e853ff6a69419f1f46c8d65f8f70faef5ac21f42f34dd05b4395fae",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -337,7 +337,7 @@
337
337
  {
338
338
  "path": "clients/bongos-client/index.d.ts",
339
339
  "mode": "0000644",
340
- "sha256": "6a35d8232a386a4cac5fd7f4368cf09a849268e56703f65531de8d7ef8e73707"
340
+ "sha256": "db3f3a76c1ae512e4b1e4d2613aa8d98ac2d9b1ae8656af6c810e2a8873652b0"
341
341
  },
342
342
  {
343
343
  "path": "clients/bongos-client/index.mjs",
@@ -2257,17 +2257,17 @@
2257
2257
  {
2258
2258
  "path": "docs/api-reference.md",
2259
2259
  "mode": "0000644",
2260
- "sha256": "acec6fe87d01bf03183c437c948d6ac524c67a871a79b1310dc3ec1cb8a24ec6"
2260
+ "sha256": "c25dbda737f9bcc02e4a8092d7bb38a67be9ef2aba93b1bfc590c52814469c06"
2261
2261
  },
2262
2262
  {
2263
2263
  "path": "docs/api/openapi.json",
2264
2264
  "mode": "0000644",
2265
- "sha256": "99a0e5d88844589d1239035827e97e5049d825dce7177f605d153a38bcde3a7f"
2265
+ "sha256": "62f196e3a1b8fb7e3dfd507fb8e86465afe94cba73af4b9690755f34e1300361"
2266
2266
  },
2267
2267
  {
2268
2268
  "path": "docs/architecture.md",
2269
2269
  "mode": "0000644",
2270
- "sha256": "345ab85b3665ae561a435cf1eccfa5ddb0464176153a12d85c84ddbc9f5cfc82"
2270
+ "sha256": "8b0fe800a7b4d60f4cb7f5eccd4fcab98d3e080a978ba3125dd9171c63cb5c78"
2271
2271
  },
2272
2272
  {
2273
2273
  "path": "docs/branding-contract.md",
@@ -2287,12 +2287,12 @@
2287
2287
  {
2288
2288
  "path": "docs/copy-inventory.md",
2289
2289
  "mode": "0000644",
2290
- "sha256": "fb27b97c3f82bffcbe68536b334f7397907e36bcc3978b6578451f6efe5124a6"
2290
+ "sha256": "4ec1c7120ed5e50105c399a93cbf8c77fc918f16e13aefcb340f4d96b3108c4d"
2291
2291
  },
2292
2292
  {
2293
2293
  "path": "docs/copy-registry.json",
2294
2294
  "mode": "0000644",
2295
- "sha256": "f3067fb3aa1876c804898bb57c16e85c7bff3e362254259f658fcb112c94d6db"
2295
+ "sha256": "95d3bee797fdd81d6f0b09a1b421e9145c37495f6b775f10cddc55ee975626d9"
2296
2296
  },
2297
2297
  {
2298
2298
  "path": "docs/design/apex-pass-2-direction.md",
@@ -2797,7 +2797,7 @@
2797
2797
  {
2798
2798
  "path": "docs/module-api-changelog.md",
2799
2799
  "mode": "0000644",
2800
- "sha256": "738e8133bb79609db71fb74862b1c7d1588848944e8b066c5ecb9b18a1b010c7"
2800
+ "sha256": "60f7e5066cd8cc5a362b2dc7173e20e2879e1f28bdc1334b4c3d0761c5d815bb"
2801
2801
  },
2802
2802
  {
2803
2803
  "path": "docs/modules-contract.md",
@@ -2887,7 +2887,7 @@
2887
2887
  {
2888
2888
  "path": "docs/page-readings.json",
2889
2889
  "mode": "0000644",
2890
- "sha256": "d40368d1f677a49d2cf7d0b1c685e8e7413136a5e57f613ab0c3004453cfcdd0"
2890
+ "sha256": "65c17b70d8590d4031ba8f082813ac30bff416360bc78a734e4532a532d44f20"
2891
2891
  },
2892
2892
  {
2893
2893
  "path": "docs/project-context.template.md",
@@ -3989,6 +3989,11 @@
3989
3989
  "mode": "0000644",
3990
3990
  "sha256": "09070e79b3e4781a185263d1bb2be364dd1225dcf6f79bdf9c21cc498fb009dd"
3991
3991
  },
3992
+ {
3993
+ "path": "migrations/core_268_builders_main_discipline.sql",
3994
+ "mode": "0000644",
3995
+ "sha256": "f5fadebea5921e58f918952d66eaae69d40016bd5782483daf4070bfa2996898"
3996
+ },
3992
3997
  {
3993
3998
  "path": "modules/agents/CLAUDE.md",
3994
3999
  "mode": "0000644",
@@ -4214,6 +4219,11 @@
4214
4219
  "mode": "0000644",
4215
4220
  "sha256": "7cb9dac9cb87b679e1ae50e4112b3a7928a38ebb9902c8947a74d17bec4d9009"
4216
4221
  },
4222
+ {
4223
+ "path": "modules/copy-desk/artist-stats.js",
4224
+ "mode": "0000644",
4225
+ "sha256": "d1b8113341aa855a00ded9c59d916ed944c4ea92ef68150f492c21e7cc355082"
4226
+ },
4217
4227
  {
4218
4228
  "path": "modules/copy-desk/docx.js",
4219
4229
  "mode": "0000644",
@@ -4237,7 +4247,7 @@
4237
4247
  {
4238
4248
  "path": "modules/copy-desk/module.json",
4239
4249
  "mode": "0000644",
4240
- "sha256": "2375fb0cfa929963d11cc135ad3a3bbb592c5e2474942229c1eecc5b839e19f3"
4250
+ "sha256": "418298167fa848e1e6f0a339d27922d6008daf5769b1534522a51a7f88b3f9c6"
4241
4251
  },
4242
4252
  {
4243
4253
  "path": "modules/copy-desk/page-data.js",
@@ -4252,7 +4262,7 @@
4252
4262
  {
4253
4263
  "path": "modules/copy-desk/page-status.js",
4254
4264
  "mode": "0000644",
4255
- "sha256": "0b96c931e6e0f8a22a3c4de287f698b9f74a45183f1b4314f66b8dfe643d33f2"
4265
+ "sha256": "b83e22529e561fad1e8e63632ef6ffd2642d861c3c0277f14c4286d07f6abbdb"
4256
4266
  },
4257
4267
  {
4258
4268
  "path": "modules/copy-desk/pages.js",
@@ -4272,7 +4282,7 @@
4272
4282
  {
4273
4283
  "path": "modules/copy-desk/routes/copy-desk.js",
4274
4284
  "mode": "0000644",
4275
- "sha256": "66cd7509e186e980b6d00e5ced844d66689e3e10fa1bb30068f3e2355fe8fcb7"
4285
+ "sha256": "b54ec33524894db892f81aa57d6feec568af3feea2d06b6dd85df0a1894ae256"
4276
4286
  },
4277
4287
  {
4278
4288
  "path": "modules/copy-desk/skills/tweak/SKILL.md",
@@ -4292,7 +4302,7 @@
4292
4302
  {
4293
4303
  "path": "modules/copy-desk/tests/copy_no_cms.mjs",
4294
4304
  "mode": "0000644",
4295
- "sha256": "68e3e04bc0330bfd86e895ace1f998e73591f3882e5e6bf15084556890e30d73"
4305
+ "sha256": "d5d01b650a04a01eabfb45cfbb8065616031482354652cbef2126f250854a6aa"
4296
4306
  },
4297
4307
  {
4298
4308
  "path": "modules/copy-desk/tests/copy_page_draft.mjs",
@@ -4649,6 +4659,11 @@
4649
4659
  "mode": "0000644",
4650
4660
  "sha256": "ce3ce114f5315c78a2feb810bce09cde84941765629f0e5a10a44aced2c34210"
4651
4661
  },
4662
+ {
4663
+ "path": "modules/economy/credits-by-craft.js",
4664
+ "mode": "0000644",
4665
+ "sha256": "fbfd7d8f0fb20c08eced9697c7d4d41653b784e5738886207cdbcb0517c29849"
4666
+ },
4652
4667
  {
4653
4668
  "path": "modules/economy/credits.js",
4654
4669
  "mode": "0000644",
@@ -4692,7 +4707,7 @@
4692
4707
  {
4693
4708
  "path": "modules/economy/reward.js",
4694
4709
  "mode": "0000644",
4695
- "sha256": "4c54857aea9bc12c59e712410b0b98124d0274dece739bfbd844f52dc6ac6880"
4710
+ "sha256": "5474fb3b913f084c93e12cbfb3e729b829181230d099274d9a15d74711286c2a"
4696
4711
  },
4697
4712
  {
4698
4713
  "path": "modules/economy/routes/cost.js",
@@ -5562,7 +5577,7 @@
5562
5577
  {
5563
5578
  "path": "modules/hall-ui/public/hall-render.js",
5564
5579
  "mode": "0000644",
5565
- "sha256": "a4e56cc0090f87d1debe306dd9caa48bdfbe63bd4b328169a4a4cbb4708d3cca"
5580
+ "sha256": "6256119e6aa53ddde4f9a6d5e218685ef5730fc4a305ce6f3d2b90c12de9a187"
5566
5581
  },
5567
5582
  {
5568
5583
  "path": "modules/hall-ui/public/hall-visual.js",
@@ -5742,7 +5757,7 @@
5742
5757
  {
5743
5758
  "path": "modules/hall-ui/public/profile.js",
5744
5759
  "mode": "0000644",
5745
- "sha256": "bc7230ecfae6376cd0e4b6dcf46e43f7b60aa5dcd166aea808aa97d831ddadbb"
5760
+ "sha256": "d5ccda2a84c90610c322e9918b87bfdc743ae3b06e47a009b1dca45cc395c07d"
5746
5761
  },
5747
5762
  {
5748
5763
  "path": "modules/hall-ui/public/profile.states.json",
@@ -6249,6 +6264,11 @@
6249
6264
  "mode": "0000644",
6250
6265
  "sha256": "e516f7951b91234c1f9dc6e327dc7365b6f6c9aad69bb3a85835061e2d072253"
6251
6266
  },
6267
+ {
6268
+ "path": "modules/ideas/ideator-stats.js",
6269
+ "mode": "0000644",
6270
+ "sha256": "5ff7f5494eab6b16494e2f83048a72e71870de82ee6b3ec58394c559f035ef75"
6271
+ },
6252
6272
  {
6253
6273
  "path": "modules/ideas/inbox.js",
6254
6274
  "mode": "0000644",
@@ -6312,7 +6332,7 @@
6312
6332
  {
6313
6333
  "path": "modules/ideas/module.json",
6314
6334
  "mode": "0000644",
6315
- "sha256": "bd0d6a232b4156b5a1fac8d3ddc543a1c0ac9aa886ca303364fdea5161342e53"
6335
+ "sha256": "207f21d62eb9c12ebf1bcd1c6c5c717a70546519a8c9cc66071b146a2b071c29"
6316
6336
  },
6317
6337
  {
6318
6338
  "path": "modules/ideas/pollers/descent-writer.js",
@@ -6342,7 +6362,7 @@
6342
6362
  {
6343
6363
  "path": "modules/ideas/routes/inbox.js",
6344
6364
  "mode": "0000644",
6345
- "sha256": "2539c5e536465066243061d7cb38137e64fc6dc434287aa6f59167d9aa0badc5"
6365
+ "sha256": "2363d8ac91b5da2e70c9c1c02b4ad39044fbe95d21d15f214b08aed5cb135aed"
6346
6366
  },
6347
6367
  {
6348
6368
  "path": "modules/ideas/routes/ratify-goal.js",
@@ -6412,7 +6432,7 @@
6412
6432
  {
6413
6433
  "path": "modules/lifecycle/activity.js",
6414
6434
  "mode": "0000644",
6415
- "sha256": "38bbb1b0f0992c655cd48f95476fbbdac11381bb929999b6da0f68fbbf802b16"
6435
+ "sha256": "e7c7db8a6faf50f3b75cb26ac33caa8357c462293e64318212ace69b0b654507"
6416
6436
  },
6417
6437
  {
6418
6438
  "path": "modules/lifecycle/cascade.js",
@@ -6477,7 +6497,7 @@
6477
6497
  {
6478
6498
  "path": "modules/lifecycle/db-analytics.js",
6479
6499
  "mode": "0000644",
6480
- "sha256": "8e8aedb44b8773760ebe0ea87b8c4f0aa98b838a69be6ae1a40c3c2e7e28b656"
6500
+ "sha256": "f17262a004d2c9d1157bdbb1a1747a59d5458364674baebec89e9a22e74f90b8"
6481
6501
  },
6482
6502
  {
6483
6503
  "path": "modules/lifecycle/db-claim-reads.js",
@@ -6537,7 +6557,7 @@
6537
6557
  {
6538
6558
  "path": "modules/lifecycle/db-tasks.js",
6539
6559
  "mode": "0000644",
6540
- "sha256": "bf527e80db47d586361be82ef568842e011484313f09cc6405d1c351f9e15df7"
6560
+ "sha256": "5f58f89cdf7055461a62c17209fbca84b11bcacc0100ec18ad6f12db3884ce06"
6541
6561
  },
6542
6562
  {
6543
6563
  "path": "modules/lifecycle/db-versions.js",
@@ -6547,7 +6567,7 @@
6547
6567
  {
6548
6568
  "path": "modules/lifecycle/db.js",
6549
6569
  "mode": "0000644",
6550
- "sha256": "d49c3a69786769c83326a0dbe31b4cb59fca5bd1ee9be222ce6445f60df99996"
6570
+ "sha256": "84b448dccaaaac7f74c91dec7aa4fc3b32f3a451e691e02d70a9113f0c5bd01c"
6551
6571
  },
6552
6572
  {
6553
6573
  "path": "modules/lifecycle/dead-deps.js",
@@ -6787,7 +6807,7 @@
6787
6807
  {
6788
6808
  "path": "modules/lifecycle/page-tweak-reads.js",
6789
6809
  "mode": "0000644",
6790
- "sha256": "7606154d0aa95475e0cd59b753d38bd00c2ce65928d843191738dcf9bdd93f72"
6810
+ "sha256": "9cc7843677c42d50d2c1a9a75e8b895fc50a2245d3baa8242076c5a67788e308"
6791
6811
  },
6792
6812
  {
6793
6813
  "path": "modules/lifecycle/page-tweak-write.js",
@@ -9367,12 +9387,12 @@
9367
9387
  {
9368
9388
  "path": "package-lock.json",
9369
9389
  "mode": "0000644",
9370
- "sha256": "1c34881ef988aef1daaca7d1f9f63d20783813fc1ddcf79da9a64f59bf49a438"
9390
+ "sha256": "604495a696c73437808848cc0c6b083f60a38d9c9599589e7d5107ec3a150c65"
9371
9391
  },
9372
9392
  {
9373
9393
  "path": "package.json",
9374
9394
  "mode": "0000644",
9375
- "sha256": "6c32b8c4acba62273ec9f209a2c1393b02383647f339d3909734bdec901eb9ac"
9395
+ "sha256": "6278722e681a62f37f21dd320837e605cb2f27daf434091e5cc12bc199c3831d"
9376
9396
  },
9377
9397
  {
9378
9398
  "path": "public-docs/index.html",
@@ -9392,7 +9412,7 @@
9392
9412
  {
9393
9413
  "path": "release-notes.json",
9394
9414
  "mode": "0000644",
9395
- "sha256": "3fe71d941f2e39b8c1ce5cc87aadeb68cf60b33808fec3dfe00394c0c65e7225"
9415
+ "sha256": "e5f5830287bcd6ea12b800a170ae7ad45e7f0ef359ef5d734fb8378e63aa2e91"
9396
9416
  },
9397
9417
  {
9398
9418
  "path": "scripts/bongos-mcp.js",
@@ -10577,7 +10597,7 @@
10577
10597
  {
10578
10598
  "path": "scripts/gds/run-unit-tests.js",
10579
10599
  "mode": "0000644",
10580
- "sha256": "1060c8a67619c8e6c0d8168d6a26644b799ed8053ab4995fd9386b55af3660c9"
10600
+ "sha256": "90c8029f97db125917048f0dbd274a127c5819e823b1bf431670bbb66d3a2817"
10581
10601
  },
10582
10602
  {
10583
10603
  "path": "scripts/gds/runner-drift.js",
@@ -11262,7 +11282,7 @@
11262
11282
  {
11263
11283
  "path": "src/bongos/db.js",
11264
11284
  "mode": "0000644",
11265
- "sha256": "c0fd77dd355dfb859c67dd802fd2f4418c41942366979cce01560e9d94bb11c4"
11285
+ "sha256": "d05a22912d5d0f21b1cc6b7231108b42d9de2686deeee8439db9f4cb518ac4ed"
11266
11286
  },
11267
11287
  {
11268
11288
  "path": "src/bongos/github-repos.js",
@@ -11399,6 +11419,11 @@
11399
11419
  "mode": "0000644",
11400
11420
  "sha256": "38c98f7cdb9dbc9d73dc53d0ad29466bc2fc8f762cd8db3961ab40df44dae11c"
11401
11421
  },
11422
+ {
11423
+ "path": "src/bongos/role-stats.js",
11424
+ "mode": "0000644",
11425
+ "sha256": "193a0b046fb321bcdb268392443fa1f37b92e7064ab5905776b6efd6ee1ea63a"
11426
+ },
11402
11427
  {
11403
11428
  "path": "src/bongos/route-rank-check.js",
11404
11429
  "mode": "0000644",
@@ -11437,7 +11462,7 @@
11437
11462
  {
11438
11463
  "path": "src/bongos/routes/builders.js",
11439
11464
  "mode": "0000644",
11440
- "sha256": "1de0a5c1cf48064964d3dec79cd8b6c44d389b6485ea18a63a8b386091bb48bd"
11465
+ "sha256": "8a6b26f85dc9743ce5197e5c2458d7e44db26c45d5a8a2ca01519ed503ac381e"
11441
11466
  },
11442
11467
  {
11443
11468
  "path": "src/bongos/routes/cli-commands.js",
@@ -11482,7 +11507,7 @@
11482
11507
  {
11483
11508
  "path": "src/bongos/routes/me.js",
11484
11509
  "mode": "0000644",
11485
- "sha256": "382c8bfbc436f157dc3d1ee297b6ab87a94d1f27837618d2b47d844033af86e0"
11510
+ "sha256": "2324e52c2c134f2914de78a6988841065d21f14e262828a48e8d291a6d11f94d"
11486
11511
  },
11487
11512
  {
11488
11513
  "path": "src/bongos/routes/modules.js",
@@ -11557,7 +11582,7 @@
11557
11582
  {
11558
11583
  "path": "src/module-api.js",
11559
11584
  "mode": "0000644",
11560
- "sha256": "4d6b2a28545380876fc0d03e74be48db1eca8320778c846e778632162ce186f5"
11585
+ "sha256": "f5eb53c5fdb1bba7c172dcf262ad5b8f624f2d881fcd4b269ed6297b6688f60a"
11561
11586
  },
11562
11587
  {
11563
11588
  "path": "src/module-loader/catalog.js",
@@ -12482,7 +12507,7 @@
12482
12507
  {
12483
12508
  "path": "tests/copy_desk_page_reads.mjs",
12484
12509
  "mode": "0000644",
12485
- "sha256": "29c591eb22b17fb86a3bff894d362f1372e41d1d0e06e3751f36da90184a425a"
12510
+ "sha256": "b84c47c44aa602c6cb13c5cbb21c27316a30297ab192301b1a4dddd9e38c98c0"
12486
12511
  },
12487
12512
  {
12488
12513
  "path": "tests/copy_desk_page_submit.mjs",
@@ -13022,7 +13047,7 @@
13022
13047
  {
13023
13048
  "path": "tests/fixtures/page-ledger.mjs",
13024
13049
  "mode": "0000644",
13025
- "sha256": "b3a9a8cb1f396760302b0b85e53ccca66145061002dabda1c1d94254a2ded399"
13050
+ "sha256": "334af36c6207995d2fa55023ba43c47cd00d41f09cfbb6a86416b4f785e85a5b"
13026
13051
  },
13027
13052
  {
13028
13053
  "path": "tests/fixtures/session-506-digest.json",
@@ -14429,6 +14454,11 @@
14429
14454
  "mode": "0000644",
14430
14455
  "sha256": "e7d7420279a2c2264268544552423406006a0e1ed3accf680ba814161cdb0e41"
14431
14456
  },
14457
+ {
14458
+ "path": "tests/main_discipline.mjs",
14459
+ "mode": "0000644",
14460
+ "sha256": "15c31505586a586701dc1a78e80f4baa98a302d56249d896aaac36847429e095"
14461
+ },
14432
14462
  {
14433
14463
  "path": "tests/main_worktree_busy_reason.mjs",
14434
14464
  "mode": "0000644",
@@ -15059,6 +15089,11 @@
15059
15089
  "mode": "0000644",
15060
15090
  "sha256": "f5e664627bf60830c241539cd001b5eebc55a5786c191154bdd6b6f3dbd745ed"
15061
15091
  },
15092
+ {
15093
+ "path": "tests/profile_role_stats.mjs",
15094
+ "mode": "0000644",
15095
+ "sha256": "f19d360e648c15576818313f80ea3079b933ccfc1f4ecb710198d993f2fa4054"
15096
+ },
15062
15097
  {
15063
15098
  "path": "tests/profile_rollup_consent.mjs",
15064
15099
  "mode": "0000644",
@@ -15669,6 +15704,11 @@
15669
15704
  "mode": "0000644",
15670
15705
  "sha256": "9c8ecadb5ffdd9dc8a7632d432f40364fde9ab21c390cbb4530005b990601c87"
15671
15706
  },
15707
+ {
15708
+ "path": "tests/role_stats_db.mjs",
15709
+ "mode": "0000644",
15710
+ "sha256": "5fb457f7a1c4f4920575dce9ed284f2b26f6fe7139f09d6a9db73e0dc5143c6e"
15711
+ },
15672
15712
  {
15673
15713
  "path": "tests/rot_inbox.mjs",
15674
15714
  "mode": "0000644",
@@ -16577,7 +16617,7 @@
16577
16617
  {
16578
16618
  "path": "tests/tweak_replaces_artist_review.mjs",
16579
16619
  "mode": "0000644",
16580
- "sha256": "aa114120d8a0dcbe8bfeadf6e359c4fa9a636a1aa7a3d8f120451a8cfe575777"
16620
+ "sha256": "16e4eb3977e7b5c2f09a402740b92ebb376a91199766034fa93f6ef34833b8a2"
16581
16621
  },
16582
16622
  {
16583
16623
  "path": "tests/ui_design_kit.mjs",
@@ -43,7 +43,7 @@ export interface GetBuildersDirectoryResponse { builders: unknown }
43
43
  export interface GetBuildersIdActiveClaimsResponse { builder_id: unknown; claims: unknown; stale_hours: unknown; stale_hours_source: unknown }
44
44
  export interface GetBuildersIdActivityResponse { builder_id: unknown; section: unknown; role: unknown; rows: unknown; total: unknown }
45
45
  export interface GetBuildersIdOnboardingResponse { builder_id: unknown; onboarding: unknown }
46
- export interface GetBuildersIdProfileResponse { builder: unknown; shipped_count: unknown; recent_ships: unknown; achievements: unknown; cross_project?: unknown; handle?: unknown }
46
+ export interface GetBuildersIdProfileResponse { builder: unknown; shipped_count: unknown; recent_ships: unknown; achievements: unknown; roles: unknown; cross_project?: unknown; handle?: unknown }
47
47
  export interface GetBuildersMePendingRankChangeResponse { change: unknown; greeting?: unknown }
48
48
  export interface GetBuildersRosterResponse { builders: unknown; stale_hours: unknown; stale_hours_source: unknown }
49
49
  export interface GetCliCommandsResponse { version: unknown; groups: unknown }
@@ -204,7 +204,7 @@ export interface PatchInboxIdRequest { status?: "open" | "promoted" | "discarded
204
204
  export interface PatchInboxIdResponse { idea: unknown }
205
205
  export interface PatchMeCrossProjectRequest { hide_stats?: boolean; account_visibility?: string; recruiter_discoverable?: boolean }
206
206
  export interface PatchMeCrossProjectResponse { hide_stats: boolean; account_visibility: unknown; recruiter_discoverable: unknown; recruiter_discoverable_effective: unknown }
207
- export interface PatchMeDisciplinesRequest { preferred_disciplines: string[] }
207
+ export interface PatchMeDisciplinesRequest { preferred_disciplines: string[]; main_discipline?: string }
208
208
  export interface PatchMeDisciplinesResponse { builder: unknown; onboarding: unknown }
209
209
  export interface PatchMeDisplayNameResponse { display_name: unknown; max_length: unknown }
210
210
  export interface PatchMeEventSoundPrefsResponse { prefs: unknown; effective: unknown; effective_wav: unknown; events: unknown }
@@ -2939,7 +2939,7 @@
2939
2939
  "builders"
2940
2940
  ],
2941
2941
  "summary": "GET /builders/:id/profile",
2942
- "description": "GET /builders/:id/profile — the viewable builder profile page's read (task 1467, goal 25 \"bx-identity\"). Returns ONE builder's public portfolio: identity + rank + economy counters + shipped-work count + recent ships + unlocked achievements. Backs the shareable /builders/profile page. rank: public — every field returned here is ALREADY world-readable: the leaderboard (GET /public/leaderboard, no auth) exposes rank, total_credits, karma, and the top achievement ids; GET /builders/:id/onboarding is likewise an unauthenticated roster-visible read. This route is a per-builder re- presentation of the SAME already-public data, so a portfolio link is shareable without a sign-in wall (that IS the feature). It deliberately WHITELISTS the public column subset off the full builder row — the private columns getBuilderById also returns (anthropic_email / anthropic_user_id / monthly_budget_usd / system_role) are NEVER spread into the JSON. A leak-prevention unit test (tests/profile_route.mjs) asserts their absence + the 404-on-unknown-id behaviour. THROTTLED since task 1002804. The global limiter meters WRITES only (rateLimitMiddleware returns early for GET) and the public read limiter is mounted under /public/*, which this is not — so this route answered at line rate. That was tolerable while it re-presented leaderboard data; it is not now that it also carries `handle`, because an id walk then yields the builder → canonical-profile-handle map in one call per builder. modules/platform-identity/routes/public-profile.js caps /profiles/:handle for exactly that mapping, so the two routes that publish it get the same ceiling. The EXISTING shared /public/* budget (120/60s per IP), not a new one — ADR 0209's rule that routes answering one question spend one budget.\n\n**Rank:** `public` — No authentication — any caller.",
2942
+ "description": "GET /builders/:id/profile — the viewable builder profile page's read (task 1467, goal 25 \"bx-identity\"). Returns ONE builder's public portfolio: identity + rank + economy counters + shipped-work count + recent ships + unlocked achievements. Backs the shareable /builders/profile page. rank: public — every field returned here is ALREADY world-readable: the leaderboard (GET /public/leaderboard, no auth) exposes rank, total_credits, karma, and the top achievement ids; GET /builders/:id/onboarding is likewise an unauthenticated roster-visible read. This route is a per-builder re- presentation of the SAME already-public data, so a portfolio link is shareable without a sign-in wall (that IS the feature). It deliberately WHITELISTS the public column subset off the full builder row — the private columns getBuilderById also returns (anthropic_email / anthropic_user_id / monthly_budget_usd / system_role) are NEVER spread into the JSON. A leak-prevention unit test (tests/profile_route.mjs) asserts their absence + the 404-on-unknown-id behaviour. `roles` (task 1004433) is the one block that is NOT a re-presentation of the leaderboard: per-craft counts and sums. The owner made them public on 2026-09-30 (RP01 decision (a): the tally and By the numbers stay public, the trail, the earnings and every Activity tab need a sign-in), so the block carries counts only — no idea title, no page wording, no task list. THROTTLED since task 1002804. The global limiter meters WRITES only (rateLimitMiddleware returns early for GET) and the public read limiter is mounted under /public/*, which this is not — so this route answered at line rate. That was tolerable while it re-presented leaderboard data; it is not now that it also carries `handle`, because an id walk then yields the builder → canonical-profile-handle map in one call per builder. modules/platform-identity/routes/public-profile.js caps /profiles/:handle for exactly that mapping, so the two routes that publish it get the same ceiling. The EXISTING shared /public/* budget (120/60s per IP), not a new one — ADR 0209's rule that routes answering one question spend one budget.\n\n**Rank:** `public` — No authentication — any caller.",
2943
2943
  "x-rank": "public",
2944
2944
  "x-source": "src/bongos/routes/builders.js",
2945
2945
  "parameters": [
@@ -11561,7 +11561,7 @@
11561
11561
  "me"
11562
11562
  ],
11563
11563
  "summary": "PATCH /me/disciplines",
11564
- "description": "Self-service edit of the authenticated builder's preferred disciplines (migrations 027 + 086 / V3.R80). Body: { preferred_disciplines: [\"artist\", ...] }. Valid elements are whatever enabledDisciplines() offers — engineer|ideator core plus any enabled module's (artist, ui); [] clears the preference (a multi-element set just means several lanes). No rank gate — a builder owns their own profile. 422 invalid_discipline if any element is out of range. rank: any-builder — self-service profile edit; documented \"no rank gate\" in the handler comment above (a builder owns their own preference).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
11564
+ "description": "Self-service edit of the authenticated builder's preferred disciplines (migrations 027 + 086 / V3.R80). Body: { preferred_disciplines: [\"artist\", ...] }. Valid elements are whatever enabledDisciplines() offers — engineer|ideator core plus any enabled module's (artist, ui); [] clears the preference (a multi-element set just means several lanes). No rank gate — a builder owns their own profile. 422 invalid_discipline if any element is out of range. rank: any-builder — self-service profile edit; documented \"no rank gate\" in the handler comment above (a builder owns their own preference). `main_discipline` (optional, task 1004433): the builder's own MAIN role, one of the crafts in the same body; null clears it, absent keeps it (see db.updateBuilderDisciplines). 422 invalid_main_discipline otherwise.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
11565
11565
  "x-rank": "any-builder",
11566
11566
  "x-source": "src/bongos/routes/me.js",
11567
11567
  "requestBody": {
@@ -22844,6 +22844,7 @@
22844
22844
  "shipped_count": {},
22845
22845
  "recent_ships": {},
22846
22846
  "achievements": {},
22847
+ "roles": {},
22847
22848
  "cross_project": {},
22848
22849
  "handle": {}
22849
22850
  },
@@ -22851,7 +22852,8 @@
22851
22852
  "builder",
22852
22853
  "shipped_count",
22853
22854
  "recent_ships",
22854
- "achievements"
22855
+ "achievements",
22856
+ "roles"
22855
22857
  ]
22856
22858
  },
22857
22859
  "GetBuildersMePendingRankChangeResponse": {
@@ -24972,6 +24974,10 @@
24972
24974
  "type": "string"
24973
24975
  },
24974
24976
  "maxItems": 16
24977
+ },
24978
+ "main_discipline": {
24979
+ "type": "string",
24980
+ "maxLength": 32
24975
24981
  }
24976
24982
  },
24977
24983
  "required": [
@@ -471,7 +471,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
471
471
  | GET | `/api/bongos/me/credits` | `any-builder` | — | GET /me/credits — the caller's own ledger. |
472
472
  | GET | `/api/bongos/me/cross-project` | `any-builder` | — | the caller's OWN cross-project record + privacy flags (own data). |
473
473
  | PATCH | `/api/bongos/me/cross-project` | `any-builder` | `hide_stats`, `account_visibility`, `recruiter_discoverable` | flip the caller's OWN privacy flags (C2's self-serve opt-out plus the task-1002966 pair; own data, keyed on the authenticated github_id —… |
474
- | PATCH | `/api/bongos/me/disciplines` | `any-builder` | `preferred_disciplines` | Self-service edit of the authenticated builder's preferred disciplines (migrations 027 + 086 / V3.R80). |
474
+ | PATCH | `/api/bongos/me/disciplines` | `any-builder` | `preferred_disciplines`, `main_discipline` | Self-service edit of the authenticated builder's preferred disciplines (migrations 027 + 086 / V3.R80). |
475
475
  | GET | `/api/bongos/me/display-name` | `any-builder` | — | Per-builder DISPLAY NAME (task 1669). |
476
476
  | PATCH | `/api/bongos/me/display-name` | `any-builder` | _undocumented_ | PATCH the display name. |
477
477
  | GET | `/api/bongos/me/event-sound-prefs` | `any-builder` | — | Per-builder per-event sound variant selection (task 582, migration 164). |
@@ -101,6 +101,7 @@ builders(id, github_id UNIQUE, github_login, display_name, avatar_url, total_cre
101
101
  (system: can't claim/earn/log-in). The cross-builder memory WRITE gate keys on this
102
102
  EXACT value, not on rank (ADR 0026 §6C) — an Archon token is rejected.
103
103
  + skill_model_prefs jsonb (mig 037), preferred_disciplines text[] (mig 027), timezone (PMS-V2),
104
+ main_discipline text NULL (core_268 — the builder chosen MAIN role; NULL = not chosen, inferred from credits),
104
105
  deactivated_at/reactivated_at/deactivated_reason (mig 025 — the /builder-exit flow; #307 guard)
105
106
  tasks ... + xenos_claimable boolean NOT NULL DEFAULT false (mig 029) -- Xenos may claim only these
106
107
  versions(id PK 'V1'|'PMS-V1'..., name, track, status, scope_doc_path, ...) -- track is free text (the product|internal CHECK was dropped in mig 112, task 1191); the valid set is instance config (config/branding.json "tracks"), not a DB constraint
@@ -1739,9 +1739,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1739
1739
  | `d73256fbc395` | certain | {…} · who votes, and how it {…} | `modules/hall-ui/public/board-room.js:449` |
1740
1740
  | `cab2a4296aec` | certain | {…} · {…} · {…}{…} | `modules/hall-ui/public/goal-inbox.js:458` |
1741
1741
  | `1ac723849449` | certain | {…} · {…}{…} | `modules/hall-ui/public/sky-interaction.js:33` |
1742
+ | `f9958dc71904` | certain | {…} — everything earned: shipped work, approved pages and ideas. | `modules/hall-ui/public/profile.js:94` |
1742
1743
  | `ddd2bfc1fb60` | certain | {…} — how to use it | `modules/hall-ui/public/modules.js:385` |
1743
1744
  | `085f93f3f775` | certain | {…} — see all standings | `modules/hall-ui/public/hall-render.js:80` |
1744
- | `f75ee96a7511` | certain | {…} — total payout from shipped work. | `modules/hall-ui/public/profile.js:94` |
1745
1745
  | `2a2728a4ec4f` | certain | {…}% of tasks complete | `modules/hall-ui/public/roadmap.js:63` |
1746
1746
  | `15e545eb3ce2` | certain | {…}, no such task | `modules/hall-ui/public/task.js:1015` |
1747
1747
  | `8944d0dcf563` | certain | {…}, on the {…} page, is where you left it. | `modules/hall-ui/public/studio.js:658` |
@@ -17259,6 +17259,15 @@
17259
17259
  "origin": "js-markup",
17260
17260
  "confidence": "certain"
17261
17261
  },
17262
+ {
17263
+ "id": "f9958dc71904",
17264
+ "surface": "builders-hall",
17265
+ "text": "{…} — everything earned: shipped work, approved pages and ideas.",
17266
+ "file": "modules/hall-ui/public/profile.js",
17267
+ "line": 94,
17268
+ "origin": "js-markup",
17269
+ "confidence": "certain"
17270
+ },
17262
17271
  {
17263
17272
  "id": "ddd2bfc1fb60",
17264
17273
  "surface": "builders-hall",
@@ -17277,15 +17286,6 @@
17277
17286
  "origin": "js-markup",
17278
17287
  "confidence": "certain"
17279
17288
  },
17280
- {
17281
- "id": "f75ee96a7511",
17282
- "surface": "builders-hall",
17283
- "text": "{…} — total payout from shipped work.",
17284
- "file": "modules/hall-ui/public/profile.js",
17285
- "line": 94,
17286
- "origin": "js-markup",
17287
- "confidence": "certain"
17288
- },
17289
17289
  {
17290
17290
  "id": "2a2728a4ec4f",
17291
17291
  "surface": "builders-hall",
@@ -2773,5 +2773,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
2773
2773
  landed since 1.20.56 with no explicit bump. run 36823118111. (task 1002620)
2774
2774
  1.20.58 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2775
2775
  landed since 1.20.57 with no explicit bump. run 36825877084. (task 1002620)
2776
+ 1.20.59 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2777
+ landed since 1.20.58 with no explicit bump. run 36828212808. (task 1002620)
2776
2778
  ---------------------------------------------------------------------------
2777
2779
  ```