@bongos/core 1.19.512 → 1.19.514

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 +77 -42
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +2 -0
  4. package/clients/bongos-client/index.cjs +2 -0
  5. package/clients/bongos-client/index.d.ts +3 -0
  6. package/clients/bongos-client/index.mjs +2 -0
  7. package/docs/adr/0182-project-visibility-two-axes.md +2 -0
  8. package/docs/adr/0239-a-recommendation-is-a-table-that-carries-its-own-reason.md +177 -0
  9. package/docs/adr/README.md +1 -0
  10. package/docs/api/openapi.json +41 -4
  11. package/docs/api-reference.md +4 -3
  12. package/docs/copy-inventory.md +36 -35
  13. package/docs/copy-registry.json +93 -74
  14. package/docs/module-api-changelog.md +4 -0
  15. package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
  16. package/modules/hall-ui/public/hall-kit.js +309 -0
  17. package/modules/hall-ui/public/hall-render.js +10 -38
  18. package/modules/hall-ui/public/profile-charts.js +58 -65
  19. package/modules/hall-ui/public/profile.css +9 -18
  20. package/modules/hall-ui/public/style.css +101 -15
  21. package/modules/hall-ui/public/watch.css +6 -14
  22. package/modules/hall-ui/public/watch.html +1 -1
  23. package/modules/hall-ui/public/watch.js +139 -54
  24. package/modules/platform-identity/platform-identity.js +24 -20
  25. package/modules/platform-identity/projects-feed.js +142 -0
  26. package/modules/platform-identity/routes/projects.js +27 -8
  27. package/modules/platform-identity/tests/platform-identity.mjs +9 -5
  28. package/modules/provisioning/recommendations.js +260 -0
  29. package/modules/provisioning/routes/provisioning.js +29 -0
  30. package/package-lock.json +2 -2
  31. package/package.json +1 -1
  32. package/src/module-api.js +1 -1
  33. package/tests/hall_audit.mjs +84 -0
  34. package/tests/hall_kit_charts.mjs +328 -0
  35. package/tests/hall_profile_world.mjs +27 -6
  36. package/tests/helpers.mjs +161 -0
  37. package/tests/joinability_invite_only.mjs +10 -2
  38. package/tests/projects_hub.mjs +5 -1
  39. package/tests/provisioning_recommendations.mjs +448 -0
  40. package/tests/task_detail_ui.mjs +1 -153
  41. package/tests/visible_projects_feed.mjs +320 -0
  42. package/tests/watch_applications_queue.mjs +381 -0
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.512",
6
- "core_contract": "1.19.512",
7
- "source_commit": "b80dfcced279a5dc071290fdc22ea3aeec3dfd70",
5
+ "core_version": "1.19.514",
6
+ "core_contract": "1.19.514",
7
+ "source_commit": "b092f2a3e4ee99d6f856ae4d1440ed723f1dcba8",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-03T18:54:15.905Z",
9
+ "built_at": "2026-09-03T19:32:24.004Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
- "docs_redacted": 429,
12
+ "docs_redacted": 430,
13
13
  "agent_docs_stubbed": 24,
14
- "functional_verbatim": 1952,
14
+ "functional_verbatim": 1958,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 2405,
20
- "tree_sha256": "382fde42e266c00ccb3f8289a487a709a55e3e606c5fc80a395a49c667f42e96",
19
+ "file_count": 2412,
20
+ "tree_sha256": "4ea8c8583161c137a8be9e3d96b1db2589a64bd504a47f7e75ebeb15232753d2",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -362,12 +362,12 @@
362
362
  {
363
363
  "path": "clients/bongos-client/README.md",
364
364
  "mode": "0000644",
365
- "sha256": "146ce9d114ec7d5a90413713b8604843c42eac060dd943648412868e214a1a6e"
365
+ "sha256": "546f5670b4637aa1d4c492a8616d5189a971c79e8e2e163d12fe11276292faa6"
366
366
  },
367
367
  {
368
368
  "path": "clients/bongos-client/bongos-client.global.js",
369
369
  "mode": "0000644",
370
- "sha256": "0e3fb901fd7110352e0edb686cfd8824d71687b88bd7e42269d0fe855177ac9f"
370
+ "sha256": "ae151ff268d04dced73fae1136c682215a02e59bae5edb68a3d6001c0143dd57"
371
371
  },
372
372
  {
373
373
  "path": "clients/bongos-client/examples/hello-world.mjs",
@@ -377,17 +377,17 @@
377
377
  {
378
378
  "path": "clients/bongos-client/index.cjs",
379
379
  "mode": "0000644",
380
- "sha256": "19f11ecf8c9eda49cd1f2ac2425f1d3d9772ad46495305d9ae4bdeadf4695ea2"
380
+ "sha256": "72d841c53787c5ad83b214c2ac816fd4cb9c97b47329eb0417b80e660a9f6b02"
381
381
  },
382
382
  {
383
383
  "path": "clients/bongos-client/index.d.ts",
384
384
  "mode": "0000644",
385
- "sha256": "4ced11579608e8fdb481a07b5555c41b3cbf3018cb3a8bd7697fb58368283bf0"
385
+ "sha256": "07554254c8559f81ec5cf45807ddccd8488732b228a618167455c932e7f05750"
386
386
  },
387
387
  {
388
388
  "path": "clients/bongos-client/index.mjs",
389
389
  "mode": "0000644",
390
- "sha256": "3d5868d134bce56923b8f0270fbb2e988dea5b6a5ea1a00b96ff8bcde06bb40e"
390
+ "sha256": "c4b04368e61803e2fe36f26ba3757aa75ada7e465384baf3e53cd012c9ce8423"
391
391
  },
392
392
  {
393
393
  "path": "clients/bongos-client/package.json",
@@ -1407,7 +1407,7 @@
1407
1407
  {
1408
1408
  "path": "docs/adr/0182-project-visibility-two-axes.md",
1409
1409
  "mode": "0000644",
1410
- "sha256": "9474378cf54f6d66269797edf6cd1d0d76014cecbfc657f53cd5892999599f20"
1410
+ "sha256": "273133f1ce79a6e67b3beaa6d993c7aa3dda23daba0beeb2e9aedf9250152e6f"
1411
1411
  },
1412
1412
  {
1413
1413
  "path": "docs/adr/0183-criteria-close-themselves.md",
@@ -1699,20 +1699,25 @@
1699
1699
  "mode": "0000644",
1700
1700
  "sha256": "fb05e36eb48861f2b32a38da04eba839f8141bd52ff9d913070bc589c115f9d5"
1701
1701
  },
1702
+ {
1703
+ "path": "docs/adr/0239-a-recommendation-is-a-table-that-carries-its-own-reason.md",
1704
+ "mode": "0000644",
1705
+ "sha256": "42b20cd6d2e8a8d76c980df73087fd404487e4c479034dbe34d8297677bd9387"
1706
+ },
1702
1707
  {
1703
1708
  "path": "docs/adr/README.md",
1704
1709
  "mode": "0000644",
1705
- "sha256": "1ec64297bc6f1858e1315b049d143de5390fb5b5843e0414f536d4fa2a42d7d5"
1710
+ "sha256": "cef542ef427dd81632465f17c6343c6b27f3ab69436eba2130c4fa4b5c9bc4ae"
1706
1711
  },
1707
1712
  {
1708
1713
  "path": "docs/api-reference.md",
1709
1714
  "mode": "0000644",
1710
- "sha256": "f9a893262b5112e48a8bffa455c8e1a7ce8aed663e34141ef9c48117882a2ad7"
1715
+ "sha256": "36baedec0a98a17dd013bf264cdb5502624de9529ed62e69aa88590574b1b236"
1711
1716
  },
1712
1717
  {
1713
1718
  "path": "docs/api/openapi.json",
1714
1719
  "mode": "0000644",
1715
- "sha256": "ec2d400cae26a7b89f644e978840927fd0fb88fc0b7b94e9f0d00dd19955aaf2"
1720
+ "sha256": "718e7ab37e024cce51fb82da0b3a535aff961d04fb0dc5e25b8ec31a61e64851"
1716
1721
  },
1717
1722
  {
1718
1723
  "path": "docs/architecture.md",
@@ -1737,12 +1742,12 @@
1737
1742
  {
1738
1743
  "path": "docs/copy-inventory.md",
1739
1744
  "mode": "0000644",
1740
- "sha256": "519630f4bda79510d5bc3f131d28ad1915517b05ec4f8dadf3081d0845bb9440"
1745
+ "sha256": "0cc8ccfda8d8e3e7b518fae7a7584bb368d7d2eac6703518404d30f0b6ead30d"
1741
1746
  },
1742
1747
  {
1743
1748
  "path": "docs/copy-registry.json",
1744
1749
  "mode": "0000644",
1745
- "sha256": "b920c2349d109b9c75c22396095d011c90edc2614f844ac27a4b3f116c805278"
1750
+ "sha256": "1003ea51740a5f71af49e05c66ba088c337185680dd92a391c959e8ea76a3f40"
1746
1751
  },
1747
1752
  {
1748
1753
  "path": "docs/design/apex-pass-2-direction.md",
@@ -2587,7 +2592,7 @@
2587
2592
  {
2588
2593
  "path": "docs/module-api-changelog.md",
2589
2594
  "mode": "0000644",
2590
- "sha256": "26d8b7f65d94927b0f382674b0421d8b5694856fd619b5c8fc57f1147f17b20d"
2595
+ "sha256": "decebcba9ee02ff15412e119309d9a37203ee82159922157b37c7cd7ddc21926"
2591
2596
  },
2592
2597
  {
2593
2598
  "path": "docs/modules-contract.md",
@@ -3957,7 +3962,7 @@
3957
3962
  {
3958
3963
  "path": "modules/dev-box/app/src/vendor/bongos-client.cjs",
3959
3964
  "mode": "0000644",
3960
- "sha256": "19f11ecf8c9eda49cd1f2ac2425f1d3d9772ad46495305d9ae4bdeadf4695ea2"
3965
+ "sha256": "72d841c53787c5ad83b214c2ac816fd4cb9c97b47329eb0417b80e660a9f6b02"
3961
3966
  },
3962
3967
  {
3963
3968
  "path": "modules/dev-box/app/test/unit.mjs",
@@ -4707,12 +4712,12 @@
4707
4712
  {
4708
4713
  "path": "modules/hall-ui/public/hall-kit.js",
4709
4714
  "mode": "0000644",
4710
- "sha256": "e392af98c2d310bfe80ccc560895dc2729abbe416087fcc7609d22dd4593484c"
4715
+ "sha256": "9fdd4fa659a6ff1f36159a89a5bab9d12009b1624f7d72f8d1296d1dffff0d3f"
4711
4716
  },
4712
4717
  {
4713
4718
  "path": "modules/hall-ui/public/hall-render.js",
4714
4719
  "mode": "0000644",
4715
- "sha256": "d3ec5ebd2a4b60f0e87d82304920905021c6ee992e6a371516317da02f78ac3e"
4720
+ "sha256": "e06761bf930a2b7bf8b0c4a3eba0532edb1a6f0d49d366b6889ebba9101e5d4f"
4716
4721
  },
4717
4722
  {
4718
4723
  "path": "modules/hall-ui/public/hall-widgets.js",
@@ -4907,7 +4912,7 @@
4907
4912
  {
4908
4913
  "path": "modules/hall-ui/public/profile-charts.js",
4909
4914
  "mode": "0000644",
4910
- "sha256": "865df71a66dd944006b01dfb1317778a1d733d9320b4486efd8ee1ed3ea76f19"
4915
+ "sha256": "6eb791bb5d73e869f1af1dbabe6fbd04eccf970b54696a89a4cd1d28e6e705df"
4911
4916
  },
4912
4917
  {
4913
4918
  "path": "modules/hall-ui/public/profile-connections.js",
@@ -4922,7 +4927,7 @@
4922
4927
  {
4923
4928
  "path": "modules/hall-ui/public/profile.css",
4924
4929
  "mode": "0000644",
4925
- "sha256": "81712abfa291664378581139a3611acaff0ebdcd2cb77d641e8543d653080c30"
4930
+ "sha256": "18d65cb2bab78487a4cbf2447154a69674291972d15256d338123c2a437abc87"
4926
4931
  },
4927
4932
  {
4928
4933
  "path": "modules/hall-ui/public/profile.html",
@@ -5057,7 +5062,7 @@
5057
5062
  {
5058
5063
  "path": "modules/hall-ui/public/style.css",
5059
5064
  "mode": "0000644",
5060
- "sha256": "287e9d4c4a2f57e812051dc6613d4c5ef493924c1a3de1b15fa91072128fa46e"
5065
+ "sha256": "801d467a63d65c24877cac2741308590b9cd66530231f77bdf7230d1c4ebe513"
5061
5066
  },
5062
5067
  {
5063
5068
  "path": "modules/hall-ui/public/task-detail.js",
@@ -5097,17 +5102,17 @@
5097
5102
  {
5098
5103
  "path": "modules/hall-ui/public/watch.css",
5099
5104
  "mode": "0000644",
5100
- "sha256": "0c877cf6decf1b7291c877ec2e6c0603c5170cfecabf0d6be15a793b6858dad8"
5105
+ "sha256": "ea2f7870bdd9383cfded8b2b09724486faa0793438dfa17bc52af189c8a81c6f"
5101
5106
  },
5102
5107
  {
5103
5108
  "path": "modules/hall-ui/public/watch.html",
5104
5109
  "mode": "0000644",
5105
- "sha256": "b20c001318da04ee5ca731702356479b0c7e4bffdd5784be9b1984db31d30777"
5110
+ "sha256": "60ffce27ce4250223dc6bbaa22e1b7b9dfb4f689bd78b6ca1c75445088c5ddb9"
5106
5111
  },
5107
5112
  {
5108
5113
  "path": "modules/hall-ui/public/watch.js",
5109
5114
  "mode": "0000644",
5110
- "sha256": "0576fa65e1ac51a3928e1ac584532b9e4db1102513d35acc5e31c1afef66c32c"
5115
+ "sha256": "f5d264fde6898c3cf82387d042d26fb434bbd8e60657c376b452f89b0a85435c"
5111
5116
  },
5112
5117
  {
5113
5118
  "path": "modules/hall-ui/public/watch.states.json",
@@ -5812,7 +5817,7 @@
5812
5817
  {
5813
5818
  "path": "modules/platform-identity/platform-identity.js",
5814
5819
  "mode": "0000644",
5815
- "sha256": "1b626dfb9b8aec98c95d94d8a831e5343018bb6164ef76a160ae6ff5e026a3ad"
5820
+ "sha256": "c58dad2f4aee4030bfc2e93904760f70185c799b388a20d715ebe70812b942ed"
5816
5821
  },
5817
5822
  {
5818
5823
  "path": "modules/platform-identity/pollers/code-sweep.js",
@@ -5824,6 +5829,11 @@
5824
5829
  "mode": "0000644",
5825
5830
  "sha256": "2e898799632a2b5c2ead9cb44fa0b8029fcb6d217f7d5f26c8a39b34c75bbea7"
5826
5831
  },
5832
+ {
5833
+ "path": "modules/platform-identity/projects-feed.js",
5834
+ "mode": "0000644",
5835
+ "sha256": "7ba4e7f2a375a1197524106605ff5dd6e4e597b2926bf6498f784ede5099a447"
5836
+ },
5827
5837
  {
5828
5838
  "path": "modules/platform-identity/publish-gate.js",
5829
5839
  "mode": "0000644",
@@ -5852,7 +5862,7 @@
5852
5862
  {
5853
5863
  "path": "modules/platform-identity/routes/projects.js",
5854
5864
  "mode": "0000644",
5855
- "sha256": "8652dbbc243f9bb10d759dd140163471d41687b405742f02b5936be818a93472"
5865
+ "sha256": "ec297f39a3d7f23b05b24ea6837bb9bfd07a12f99734788e9332769c59acc7b7"
5856
5866
  },
5857
5867
  {
5858
5868
  "path": "modules/platform-identity/routes/public-profile.js",
@@ -5882,7 +5892,7 @@
5882
5892
  {
5883
5893
  "path": "modules/platform-identity/tests/platform-identity.mjs",
5884
5894
  "mode": "0000644",
5885
- "sha256": "6151b6e7d5c4336fece03d0c29dbc94493329ba3bd4d8782702a2d581e5a4cc7"
5895
+ "sha256": "a0ed65254f629cc29f4f1093c54d5e78a148d5bc7f072fb98819562a96f7dd37"
5886
5896
  },
5887
5897
  {
5888
5898
  "path": "modules/platform-identity/ui/.gitkeep",
@@ -5984,10 +5994,15 @@
5984
5994
  "mode": "0000644",
5985
5995
  "sha256": "27046325beffad5d1edfcc91c331048038900ef7d32f1d38796755c7990ba202"
5986
5996
  },
5997
+ {
5998
+ "path": "modules/provisioning/recommendations.js",
5999
+ "mode": "0000644",
6000
+ "sha256": "8c4b2d8d17b80229c371b82ac9a5a2cf2fa979683ac586e8b833ca0a309a92fc"
6001
+ },
5987
6002
  {
5988
6003
  "path": "modules/provisioning/routes/provisioning.js",
5989
6004
  "mode": "0000644",
5990
- "sha256": "338e135f492e584aa4539d4a64d7c881b964c9ffa8428ff3359ad96d80b82a5c"
6005
+ "sha256": "9285f3f2d426305c060eef4b3b98ae64fc386e4ce487f99d9ad59d9921dc493e"
5991
6006
  },
5992
6007
  {
5993
6008
  "path": "modules/provisioning/starter-bundles.js",
@@ -7247,12 +7262,12 @@
7247
7262
  {
7248
7263
  "path": "package-lock.json",
7249
7264
  "mode": "0000644",
7250
- "sha256": "63c01590a251d6ec16dde2e0be5d843e12ff40955733268f6d322718f1e807be"
7265
+ "sha256": "9c126ed4b632afd9452b01fa9e08eb97295699e99efc9c7d4040a761cac7f58d"
7251
7266
  },
7252
7267
  {
7253
7268
  "path": "package.json",
7254
7269
  "mode": "0000644",
7255
- "sha256": "4bbced9436a337f2b2ea9fe5445bf6f9f94354ffeda4d1b1766cd12f4e9f74d9"
7270
+ "sha256": "7cc213de070341042dae24c32b6fc458ae6912399a715d50b18dd92c52548fd8"
7256
7271
  },
7257
7272
  {
7258
7273
  "path": "public-docs/index.html",
@@ -8922,7 +8937,7 @@
8922
8937
  {
8923
8938
  "path": "src/module-api.js",
8924
8939
  "mode": "0000644",
8925
- "sha256": "379afd7239016bc0e504bc3b73596c35cb71a074a6b743f32c76c5a24493a44e"
8940
+ "sha256": "ace7f9365df0b8019d1fbc1758832db878c9b00ff59583a5ddcd839bbb69b1eb"
8926
8941
  },
8927
8942
  {
8928
8943
  "path": "src/module-loader/catalog.js",
@@ -10302,7 +10317,7 @@
10302
10317
  {
10303
10318
  "path": "tests/hall_audit.mjs",
10304
10319
  "mode": "0000644",
10305
- "sha256": "7df5602bb92b44186613870501ecb4e959c9288f8d103cfc8075a3a24d51d840"
10320
+ "sha256": "0b30e949b0479adb4b436aa32e741c9f2ab3925a1ac4327daf6e8a95700a8c14"
10306
10321
  },
10307
10322
  {
10308
10323
  "path": "tests/hall_board_world.mjs",
@@ -10324,6 +10339,11 @@
10324
10339
  "mode": "0000644",
10325
10340
  "sha256": "1d9c1d345a6fe25eacf810703a3e7f9f3b33f8e982aef49364e19eb4469de668"
10326
10341
  },
10342
+ {
10343
+ "path": "tests/hall_kit_charts.mjs",
10344
+ "mode": "0000644",
10345
+ "sha256": "475c712af2b45fed7863b486c3d2ed3b96e955dccb9acc5909999db3990843d5"
10346
+ },
10327
10347
  {
10328
10348
  "path": "tests/hall_nav.mjs",
10329
10349
  "mode": "0000644",
@@ -10352,7 +10372,7 @@
10352
10372
  {
10353
10373
  "path": "tests/hall_profile_world.mjs",
10354
10374
  "mode": "0000644",
10355
- "sha256": "9e5047b39d55875e167c992157c6c04a9a766ec331c1a3bf343fe7ea194a8309"
10375
+ "sha256": "b35d647c4cb7b90be70dee8e7245396cc901479992fafbf19ceef734d8195399"
10356
10376
  },
10357
10377
  {
10358
10378
  "path": "tests/hall_reading_world.mjs",
@@ -10402,7 +10422,7 @@
10402
10422
  {
10403
10423
  "path": "tests/helpers.mjs",
10404
10424
  "mode": "0000644",
10405
- "sha256": "89d0ebdf842108bcf807bd08663e9f83566d9b0ae80e72ba038f8d4f0b30b0f8"
10425
+ "sha256": "b3f0a87c51c9e655c712db00a0a8763e2fc08e4de3c6904c6080385e7c7dad14"
10406
10426
  },
10407
10427
  {
10408
10428
  "path": "tests/hierarchy-config.mjs",
@@ -10632,7 +10652,7 @@
10632
10652
  {
10633
10653
  "path": "tests/joinability_invite_only.mjs",
10634
10654
  "mode": "0000644",
10635
- "sha256": "082693b5e07c1c25cec17cde7f93a8716aafa94ead9b1cee76b1643f30edff79"
10655
+ "sha256": "5311e076e8a72b993a235e57ebc54c9ecd529ccd31b65609432677a12e15e85d"
10636
10656
  },
10637
10657
  {
10638
10658
  "path": "tests/joinability_open.mjs",
@@ -11122,7 +11142,7 @@
11122
11142
  {
11123
11143
  "path": "tests/projects_hub.mjs",
11124
11144
  "mode": "0000644",
11125
- "sha256": "eeb54786e5cb1211f0036d7c72119082fe47c023502c017b0092c6b22f60f0c1"
11145
+ "sha256": "22461d4febf616202af96aa37fc940a686841bbf68155094526455ae85ab9886"
11126
11146
  },
11127
11147
  {
11128
11148
  "path": "tests/projects_hub_pre_uat.mjs",
@@ -11174,6 +11194,11 @@
11174
11194
  "mode": "0000644",
11175
11195
  "sha256": "97d04ee39cc06b720d4a5b42f3e3cc614f64d9462b27471a1af7598b5e2929be"
11176
11196
  },
11197
+ {
11198
+ "path": "tests/provisioning_recommendations.mjs",
11199
+ "mode": "0000644",
11200
+ "sha256": "0557876002c1f0efde5a8e7c87702fa57df3a9efb26ea93b077969bcc10e3637"
11201
+ },
11177
11202
  {
11178
11203
  "path": "tests/provisioning_restart.mjs",
11179
11204
  "mode": "0000644",
@@ -11847,7 +11872,7 @@
11847
11872
  {
11848
11873
  "path": "tests/task_detail_ui.mjs",
11849
11874
  "mode": "0000644",
11850
- "sha256": "5e7150f8651a3c147b17f51800f5f8afa1e9534b3ec545584e5c37792475b2aa"
11875
+ "sha256": "d7b12d56b50a0412d50f3558065c681d92c0c631edfef5553164e646979e6fa5"
11851
11876
  },
11852
11877
  {
11853
11878
  "path": "tests/task_goal_link.mjs",
@@ -11999,11 +12024,21 @@
11999
12024
  "mode": "0000644",
12000
12025
  "sha256": "2a381bab380342e4fc556211d4821c85fdde1f676a6c5c6aa2421a89a573cd27"
12001
12026
  },
12027
+ {
12028
+ "path": "tests/visible_projects_feed.mjs",
12029
+ "mode": "0000644",
12030
+ "sha256": "4bf47b6aee92c54099c583726d05421a433ac5b5e82792a848d11c80d7ee7bd1"
12031
+ },
12002
12032
  {
12003
12033
  "path": "tests/wandering_prefs.mjs",
12004
12034
  "mode": "0000644",
12005
12035
  "sha256": "745a868a2e13f34afd29f96840102205792bac810f2fd911c7da00f6a5695242"
12006
12036
  },
12037
+ {
12038
+ "path": "tests/watch_applications_queue.mjs",
12039
+ "mode": "0000644",
12040
+ "sha256": "b1f7df5aa40b89f8737c76d94def15c539514f7f439cca79a034bf37b922158d"
12041
+ },
12007
12042
  {
12008
12043
  "path": "tests/web_admission_status.mjs",
12009
12044
  "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
- - 346 operations across 53 resource groups
8
+ - 347 operations across 53 resource groups
9
9
 
10
10
  ## Install
11
11
 
@@ -669,6 +669,8 @@ function createClient(opts = {}) {
669
669
  postProvisioningInstancesIdTeardown: (args) => request("POST", "/provisioning/instances/{id}/teardown", { hasBody: true }, args),
670
670
  // GET /provisioning/onboard-plan — rank: public — GET /provisioning/onboard-plan
671
671
  getProvisioningOnboardPlan: (args) => request("GET", "/provisioning/onboard-plan", { hasBody: false }, args),
672
+ // GET /provisioning/recommendations — rank: public — GET /provisioning/recommendations
673
+ getProvisioningRecommendations: (args) => request("GET", "/provisioning/recommendations", { hasBody: false }, args),
672
674
  // GET /provisioning/slug-available — rank: any-builder — GET /provisioning/slug-available
673
675
  getProvisioningSlugAvailable: (args) => request("GET", "/provisioning/slug-available", { hasBody: false }, args),
674
676
  // GET /provisioning/starter-bundles — rank: public — GET /provisioning/starter-bundles
@@ -668,6 +668,8 @@ function createClient(opts = {}) {
668
668
  postProvisioningInstancesIdTeardown: (args) => request("POST", "/provisioning/instances/{id}/teardown", { hasBody: true }, args),
669
669
  // GET /provisioning/onboard-plan — rank: public — GET /provisioning/onboard-plan
670
670
  getProvisioningOnboardPlan: (args) => request("GET", "/provisioning/onboard-plan", { hasBody: false }, args),
671
+ // GET /provisioning/recommendations — rank: public — GET /provisioning/recommendations
672
+ getProvisioningRecommendations: (args) => request("GET", "/provisioning/recommendations", { hasBody: false }, args),
671
673
  // GET /provisioning/slug-available — rank: any-builder — GET /provisioning/slug-available
672
674
  getProvisioningSlugAvailable: (args) => request("GET", "/provisioning/slug-available", { hasBody: false }, args),
673
675
  // GET /provisioning/starter-bundles — rank: public — GET /provisioning/starter-bundles
@@ -97,6 +97,7 @@ export interface GetProvisioningInstancesIdResponse { instance: unknown; open_in
97
97
  export interface GetProvisioningInstancesIdSettingsResponse { ok: boolean; settings: unknown; planet: unknown; options: unknown }
98
98
  export interface GetProvisioningInstancesResponse { instances: unknown }
99
99
  export interface GetProvisioningOnboardPlanResponse { mode: unknown; steps: unknown }
100
+ export interface GetProvisioningRecommendationsResponse { recommendations: unknown }
100
101
  export interface GetProvisioningSlugAvailableResponse { slug: unknown; available: unknown; reason: unknown; address: unknown }
101
102
  export interface GetProvisioningStarterBundlesResponse { core: unknown; bundles: unknown }
102
103
  export interface GetPublicBlockersIdResponse { blocker: unknown }
@@ -980,6 +981,8 @@ export interface BongosClient {
980
981
  postProvisioningInstancesIdTeardown(args?: RequestArgs): Promise<PostProvisioningInstancesIdTeardownResponse>;
981
982
  /** GET /provisioning/onboard-plan — rank: public */
982
983
  getProvisioningOnboardPlan(args?: RequestArgs): Promise<GetProvisioningOnboardPlanResponse>;
984
+ /** GET /provisioning/recommendations — rank: public */
985
+ getProvisioningRecommendations(args?: RequestArgs): Promise<GetProvisioningRecommendationsResponse>;
983
986
  /** GET /provisioning/slug-available — rank: any-builder */
984
987
  getProvisioningSlugAvailable(args?: RequestArgs): Promise<GetProvisioningSlugAvailableResponse>;
985
988
  /** GET /provisioning/starter-bundles — rank: public */
@@ -665,6 +665,8 @@ export function createClient(opts = {}) {
665
665
  postProvisioningInstancesIdTeardown: (args) => request("POST", "/provisioning/instances/{id}/teardown", { hasBody: true }, args),
666
666
  // GET /provisioning/onboard-plan — rank: public — GET /provisioning/onboard-plan
667
667
  getProvisioningOnboardPlan: (args) => request("GET", "/provisioning/onboard-plan", { hasBody: false }, args),
668
+ // GET /provisioning/recommendations — rank: public — GET /provisioning/recommendations
669
+ getProvisioningRecommendations: (args) => request("GET", "/provisioning/recommendations", { hasBody: false }, args),
668
670
  // GET /provisioning/slug-available — rank: any-builder — GET /provisioning/slug-available
669
671
  getProvisioningSlugAvailable: (args) => request("GET", "/provisioning/slug-available", { hasBody: false }, args),
670
672
  // GET /provisioning/starter-bundles — rank: public — GET /provisioning/starter-bundles
@@ -161,6 +161,8 @@ Until then: `stealth` unqualified in product code and copy means the project sta
161
161
  - Anything reading `featured = true AND status = 'active'` as "is this public" is now wrong and must be found. `modules/platform-identity/routes/projects.js` is the known site.
162
162
  - **R16 makes D3's bound real, and D4's gate reach a second module.** Shipping R16 (task 1002335) surfaced one thing this ADR left implicit. D3 says `featured` may never put an unpublishable project on the map, so `PATCH /projects/:id/featured` now refuses a dark-matter row (409 `not_publishable`, `missing` in the details); un-featuring stays unconditional, since an already-featured husk must remain removable. And D4's "name what is missing" is owed to the owner *before* their project is ever catalogued on the hub — which is the `provisioning` plane, a different module that ADR 0083 forbids from importing `platform-identity`. Rather than let a two-field rule exist twice, the gate is published as a kernel seam port, `project.publishGate` (`modules/platform-identity/publish-gate.js`). `provisioning` resolves it **optionally** and declares no `consumes`: `platform-identity` is hub-only, the public map is a hub concept, and a platform without one must answer "no verdict" rather than invent a local rule — which is the same drift-avoidance argument that produced `publishableSql` in the first place.
163
163
 
164
+ - **R06 landed the predicate swap and the redaction, and settled three things this ADR left to the implementer** (task 1002325, `modules/platform-identity/projects-feed.js`). (a) **A black hole carries no stable per-project key.** D2a lists `name`/`tagline`/`art_url`/`origin`, and an id looks harmless beside them — but any identifier that survives a state change lets an observer who kept yesterday's public feed diff it against today's and *name* the project that went stealth. So stealth rows are byte-identical to one another and the feed grew no public id at all; the orbs page keys by position. (b) **The redaction is an ALLOW-list, not a deny-list** — every key nulled except `state` and `orb` — so a column added to the feed later is anonymous without anyone remembering to come back to it, and it NULLS rather than deletes, keeping the feed's "never drop a key" contract. (c) **An unrecognised `visibility` draws as a black hole, not a planet**: this mapping is a privacy boundary, so a fourth enum value added without mapping it must fail closed. Two smaller notes: the route PATH keeps the word `featured` (it is rank:public and CORS-open, already fetched by a static site and other origins — renaming it would break them for nothing, and `ORDER BY featured DESC` is where the flag's D3 ranking job now lives); and `getRollupForBuilder`'s `is_public` was deliberately left on the OLD `featured AND active` predicate rather than widened with the feed, because a stealth project is on the map *anonymously* and naming it in a builder's profile would be the exact leak D2a forbids — how much of a cross-project record may be NAMED is ADR 0171 D2's question, and under-naming is the safe direction meanwhile.
165
+
164
166
  ## Alternatives rejected
165
167
 
166
168
  - **A stored four-valued enum including `unlisted`.** Rejected: it makes "unlisted" a choice competing with `private`, and it lets a project be simultaneously "publishable" and "unlisted" — two sources of truth for one question, which is the bug the derived gate prevents by construction.
@@ -0,0 +1,177 @@
1
+ # 0239 — A recommendation is a table that carries its own reason; governance is a preview and invites are a seam
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-09-03
5
+ - **Tasks:** [#1002336](https://cloudbongos.com/builders#/task/1002336) (this decision — BV1.R17)
6
+ - **Goal:** [#1000046](https://cloudbongos.com/builders#/goal/1000046) — Project creation: visibility and
7
+ customization; criteria `proj-module-select` ("additional modules are recommended (rule-based) from the
8
+ project's details"), `proj-governance-reco` ("a recommended governance setup … derived from its details"),
9
+ `proj-invite-builders` ("the owner can optionally invite guilds or top builders")
10
+ - **Related:** [ADR 0237](<redacted>.md)
11
+ (R19, the per-type preset this adjusts), [ADR 0182](<redacted>.md) D4 (skipping the
12
+ interview is a supported answer), [ADR 0083](<redacted>.md) (the
13
+ one-way import rule that makes the invite lookup a seam),
14
+ task [#1002334](https://cloudbongos.com/builders#/task/1002334) (R15, the interview whose answer this reads),
15
+ task [#1002772](https://cloudbongos.com/builders#/task/1002772) (the declared project type),
16
+ task [#1003500](https://cloudbongos.com/builders#/task/1003500) / idea 1000552 (the deferred AI layer)
17
+
18
+ ## 1. The problem
19
+
20
+ Three of goal 1000046's criteria ask the same question in three places: after an
21
+ owner answers the optional project-detail interview, what do we *recommend* — which
22
+ modules, which governance setup, which builders to invite. The goal's own text pins
23
+ the near term: "near-term recommendations are rule-based and module search is
24
+ lexical; the AI/embeddings layer … is a deferred follow-up captured in the idea
25
+ inbox."
26
+
27
+ R19 ([ADR 0237](<redacted>.md))
28
+ already answered the type half — a starter bundle per declared project type — and
29
+ said explicitly that it is "a declaration and not a rule engine … R17/R22 own the
30
+ layer that reasons." This is that layer.
31
+
32
+ ## 2. Two inputs, and the description is not one of them
33
+
34
+ The engine reads exactly two things, and they arrive separately because they are
35
+ stored separately: `type` is a column (the closed set task 1002772 fixed —
36
+ `game · research · business · non-profit · not-sure`) and `team_shape` is the one
37
+ closed-answer key the R15 interview collects (`PROJECT_DETAIL_VOCAB.team_shape ∈
38
+ solo | small-team | community`). The interview deliberately does not re-ask the type
39
+ (ADR 0237 §2), so `recommendationsForDetails({ type, team_shape })` is the file that
40
+ puts the two back together, and a caller holding a row passes
41
+ `{ type: row.type, ...projectDetail(row) }`.
42
+
43
+ The interview's *third* answer — the free-text `description` — is deliberately
44
+ **not** read. Inferring a bundle from prose is the deferred semantic layer
45
+ ([#1003500](https://cloudbongos.com/builders#/task/1003500), idea 1000552), and ADR
46
+ 0237 §7 already rejected it once for the same reason.
47
+
48
+ ## 3. A table, and every row carries the sentence that explains it
49
+
50
+ The engine is three frozen tables and a resolver over them — not a scorer, not a
51
+ weighting, not a model:
52
+
53
+ | table | keyed on | effect |
54
+ |---|---|---|
55
+ | `TEAM_SHAPE_RULES` | `team_shape` | add/remove ONE opt-in module from the type's bundle |
56
+ | `GOVERNANCE_RULES` | `team_shape` | a named preset out of `GOVERNANCE_PRESETS` |
57
+ | `INVITE_RULES` | `team_shape` | a `seeking` descriptor, or `null` for "suggest nobody" |
58
+
59
+ Every row carries a `reason` — one sentence in the owner's own words, shipped
60
+ alongside the effect rather than reconstructed by whichever surface renders it. That
61
+ is the constraint that makes the whole thing auditable: a recommendation an owner
62
+ cannot be told the reason for is one they cannot disagree with, and a reason written
63
+ separately from the rule drifts from it the first time either changes.
64
+
65
+ The three bundle rules today: `community` **adds** `discord` (somewhere for it to
66
+ gather); `small-team` **adds** `dev-box` (one shared environment); `solo` **removes**
67
+ `dev-box` (your own machine is the setup). They are few for the reason ADR 0237 §4
68
+ gave — today's opt-in catalog is three modules wide, and a preselect an owner must
69
+ audit is worse than none. The rules' job is to correct a preset the owner's answer
70
+ contradicts, not to re-derive it.
71
+
72
+ ## 4. `adjustments` is a delta — a rule that changes nothing claims nothing
73
+
74
+ `bundle.adjustments` lists only the rules that ACTUALLY moved the module list. The
75
+ game bundle already carries `discord`, so a `community` answer records no adjustment
76
+ even though its condition matched; the non-profit bundle has no `dev-box`, so a
77
+ `solo` answer removes nothing and says nothing.
78
+
79
+ The alternative — record the reason whenever the condition matches — was rejected
80
+ because it conflates two different sentences: "discord is on because your project is
81
+ a game" (the bundle, R19's opinion) and "we switched discord on because you said
82
+ community" (the rule). A picker rendering the second over a module the owner would
83
+ have had anyway is telling them something they can check and find false.
84
+
85
+ ## 5. Governance is a named preview, never an applied setting
86
+
87
+ Criterion `proj-governance-reco` says it out loud: the recommendation "depends on the
88
+ governance module (goal 1000030), which is planned but not yet built." So a preset
89
+ here is a **name plus one sentence of what living under it feels like** — `owner-only`
90
+ / `trusted-team` / `open-contribution` — and never a set of roles or permissions,
91
+ because there is nowhere to put them.
92
+
93
+ Every recommendation carries `governance.applied: false`. A constant field looks
94
+ redundant until you count the surfaces that otherwise hardcode the same fact: R25's
95
+ preview step ([#1002344](https://cloudbongos.com/builders#/task/1002344)), R18's proof
96
+ ([#1002337](https://cloudbongos.com/builders#/task/1002337)), the wizard and the
97
+ project page. One flag flips when goal 1000030 lands; a test pins it false until then.
98
+
99
+ ## 6. Invites are a seam, because the leaderboard is a sibling module
100
+
101
+ `invites.suggested` is **always empty**, and that is a decision rather than an
102
+ unfinished edge. Ranking builders means querying the leaderboard, which lives in
103
+ `economy` — a sibling module `provisioning` may not import (the one-way rule, ADR
104
+ 0083). Making the route do it instead would cost the engine's purity, put a database
105
+ read behind a public endpoint, and duplicate work
106
+ [#1002347](https://cloudbongos.com/builders#/task/1002347) (R28) already owns and
107
+ whose dependency is R27, not R17.
108
+
109
+ So the engine emits what to look for — `invites.seeking = { kind: 'top-builders',
110
+ limit }`, or `null` for "suggest nobody" — and R28 turns it into names. `null` is a
111
+ real answer here: a solo builder is suggested nobody on purpose, which is a different
112
+ statement from an empty list nobody has filled yet.
113
+
114
+ ## 7. Skipping is an answer, and every default is the narrowest one
115
+
116
+ The interview is optional (ADR 0182 D4), so every table has a stated default for
117
+ "nobody said" and each is deliberately the narrowest option: the type's own bundle
118
+ unadjusted, `owner-only` governance, and no invites. Widening later costs one
119
+ setting; a project that quietly granted strangers a role it was never asked to grant
120
+ is not recovered by setting it back.
121
+
122
+ An **off-vocabulary** `team_shape` — absent, misspelled, or a value that has since
123
+ left the vocabulary — reads as *no answer*, exactly as `normalizeProjectDetail` drops
124
+ it on the way in. The route follows the same rule: a missing or unusable query value
125
+ returns 200 with the defaults, never a 400, because refusing the request would make
126
+ the supported path an error.
127
+
128
+ `tailored: boolean` is the machine-readable half of criterion
129
+ `proj-detail-interview`'s split ("completing it produces tailored recommendations;
130
+ skipping produces sensible defaults") — false exactly when no detail answer shaped
131
+ anything. R18 is the live proof of that line.
132
+
133
+ ## 8. The read surface
134
+
135
+ `GET /provisioning/recommendations?type=&team_shape=` returns
136
+ `{ recommendations: { type, teamShape, tailored, bundle, governance, invites } }`.
137
+ `bundle` is ADR 0237 §5's shape with `adjustments` added, so R20's picker
138
+ ([#1002339](https://cloudbongos.com/builders#/task/1002339)) and this engine resolve
139
+ through the same `bundleForProjectType` and can never name different modules — a test
140
+ asserts that against the live `starter-bundles` route.
141
+
142
+ `rank: public`, the same absent gate as `starter-bundles` and `onboard-plan`: the
143
+ signed-out wizard asks while the owner is still answering, *before* any row exists to
144
+ be own-scoped against, and the answer is a declaration that names nothing private.
145
+ The route touches no database, and the test proves it by stubbing `pool` to throw.
146
+
147
+ ## 9. Consequences
148
+
149
+ - **The UI is not wired here.** R20 renders the picker, R22
150
+ ([#1002341](https://cloudbongos.com/builders#/task/1002341)) surfaces these
151
+ recommendations inside it, and R18 proves the details→recs / skip→defaults split.
152
+ The creation wizard currently hardcodes a `TEAM_META` copy table in
153
+ `modules/public-landing/public/projects.html` that says roughly what
154
+ `governance.preview` now says — R22 should collapse that duplicate into this route
155
+ rather than leave one sentence written twice.
156
+ - **Adding a fourth team-shape answer is a two-file change.** The interview vocabulary
157
+ and this file, and `tests/provisioning_recommendations.mjs` fails the build if a
158
+ vocabulary value has no governance rule and no invite rule.
159
+ - **A recommendation is still never a publish precondition** (ADR 0182 D4 — the bar is
160
+ name + description alone), and taking or declining one cannot move a project's
161
+ dark-matter state.
162
+
163
+ ## 10. Rejected
164
+
165
+ - **Reading the free-text description** — that is the deferred AI/semantic layer
166
+ ([#1003500](https://cloudbongos.com/builders#/task/1003500)), and the goal pins the
167
+ near term as rule-based.
168
+ - **Filling `invites.suggested` from `GET /public/leaderboard`** — the route exists and
169
+ is public, but reaching it means importing a sibling module, and R28 owns that work
170
+ behind a different dependency.
171
+ - **A scoring function over weighted signals** — with two inputs and three opt-in
172
+ modules there is nothing to weigh, and a score cannot be shown to an owner as a
173
+ sentence they can disagree with.
174
+ - **Recording a reason for every matched condition** — see §4; it makes a claim the
175
+ owner can check and find false.
176
+ - **Refusing an unknown `team_shape` with a 400** — skipping is the supported path, so
177
+ the shape of a skipped answer must not be an error.