@bongos/core 1.21.153 → 1.21.155
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 +26 -26
- package/docs/api/openapi.json +1 -1
- package/docs/copy-inventory.md +34 -19
- package/docs/copy-registry.json +156 -21
- package/docs/module-api-changelog.md +4 -0
- package/docs/modules-contract.md +1 -0
- package/docs/page-readings.json +22 -20
- package/modules/hall-ui/public/modules.html +4 -1
- package/modules/hall-ui/public/modules.js +32 -1
- package/modules/hall-ui/records/catalog.md +2 -0
- package/modules/lifecycle/criterion-uat.js +7 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +16 -0
- package/scripts/gds/copy-inventory.js +7 -3
- package/src/bongos/module-listing.js +41 -5
- package/src/bongos/routes/modules.js +11 -3
- package/src/module-api.js +1 -1
- package/tests/copy_inventory.mjs +21 -5
- package/tests/criterion_uat.mjs +19 -0
- package/tests/hall_catalog_world.mjs +13 -1
- package/tests/module_store_listing.mjs +78 -2
package/docs/copy-registry.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"generator": "scripts/gds/copy-inventory.js",
|
|
4
4
|
"goal": 1000074,
|
|
5
5
|
"counts": {
|
|
6
|
-
"strings":
|
|
7
|
-
"unique_ids":
|
|
8
|
-
"certain":
|
|
6
|
+
"strings": 2784,
|
|
7
|
+
"unique_ids": 2363,
|
|
8
|
+
"certain": 2784,
|
|
9
9
|
"heuristic": 0,
|
|
10
10
|
"duplicate_ids": 241
|
|
11
11
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"builders-hall": {
|
|
14
14
|
"at": "modules/hall-ui/public",
|
|
15
15
|
"files": 148,
|
|
16
|
-
"strings":
|
|
16
|
+
"strings": 1964
|
|
17
17
|
},
|
|
18
18
|
"status-dashboard": {
|
|
19
19
|
"at": "modules/status-ui/public",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"landing": {
|
|
24
24
|
"at": "modules/public-landing/public",
|
|
25
25
|
"files": 9,
|
|
26
|
-
"strings":
|
|
26
|
+
"strings": 720
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"blind_spots": [
|
|
@@ -3054,11 +3054,11 @@
|
|
|
3054
3054
|
"confidence": "certain"
|
|
3055
3055
|
},
|
|
3056
3056
|
{
|
|
3057
|
-
"id": "
|
|
3057
|
+
"id": "e395cd11edab",
|
|
3058
3058
|
"surface": "builders-hall",
|
|
3059
|
-
"text": "A part is strong at 80 out of 100 or more, and weak below the listing floor. A part with no data yet is not counted against a module.",
|
|
3059
|
+
"text": "A part is strong at 80 out of 100 or more, and weak below the listing floor. A part with no data yet is not counted against a module. Sort by a part to see the modules strongest at it first; a module with no score for that part goes last, and a new module is never ranked.",
|
|
3060
3060
|
"file": "modules/hall-ui/public/modules.html",
|
|
3061
|
-
"line":
|
|
3061
|
+
"line": 90,
|
|
3062
3062
|
"origin": "html-text",
|
|
3063
3063
|
"confidence": "certain"
|
|
3064
3064
|
},
|
|
@@ -3481,7 +3481,7 @@
|
|
|
3481
3481
|
"surface": "builders-hall",
|
|
3482
3482
|
"text": "Also available as a Claude page",
|
|
3483
3483
|
"file": "modules/hall-ui/public/modules.html",
|
|
3484
|
-
"line":
|
|
3484
|
+
"line": 103,
|
|
3485
3485
|
"origin": "html-text",
|
|
3486
3486
|
"confidence": "certain"
|
|
3487
3487
|
},
|
|
@@ -5209,7 +5209,7 @@
|
|
|
5209
5209
|
"surface": "builders-hall",
|
|
5210
5210
|
"text": "Could not load modules.",
|
|
5211
5211
|
"file": "modules/hall-ui/public/modules.js",
|
|
5212
|
-
"line":
|
|
5212
|
+
"line": 489,
|
|
5213
5213
|
"origin": "js-notice",
|
|
5214
5214
|
"confidence": "certain"
|
|
5215
5215
|
},
|
|
@@ -5398,7 +5398,7 @@
|
|
|
5398
5398
|
"surface": "builders-hall",
|
|
5399
5399
|
"text": "Could not reach the submit endpoint.",
|
|
5400
5400
|
"file": "modules/hall-ui/public/modules.js",
|
|
5401
|
-
"line":
|
|
5401
|
+
"line": 467,
|
|
5402
5402
|
"origin": "js-notice",
|
|
5403
5403
|
"confidence": "certain"
|
|
5404
5404
|
},
|
|
@@ -9376,7 +9376,7 @@
|
|
|
9376
9376
|
"surface": "builders-hall",
|
|
9377
9377
|
"text": "No real-world data yet, so it is listed but not ranked.",
|
|
9378
9378
|
"file": "modules/hall-ui/public/modules.js",
|
|
9379
|
-
"line":
|
|
9379
|
+
"line": 235,
|
|
9380
9380
|
"origin": "js-markup",
|
|
9381
9381
|
"confidence": "certain"
|
|
9382
9382
|
},
|
|
@@ -10015,7 +10015,7 @@
|
|
|
10015
10015
|
"surface": "builders-hall",
|
|
10016
10016
|
"text": "Nothing to submit — every module here ships with the core.",
|
|
10017
10017
|
"file": "modules/hall-ui/public/modules.js",
|
|
10018
|
-
"line":
|
|
10018
|
+
"line": 428,
|
|
10019
10019
|
"origin": "js-text-assign",
|
|
10020
10020
|
"confidence": "certain"
|
|
10021
10021
|
},
|
|
@@ -11896,7 +11896,7 @@
|
|
|
11896
11896
|
"surface": "builders-hall",
|
|
11897
11897
|
"text": "Save as PDF",
|
|
11898
11898
|
"file": "modules/hall-ui/public/modules.html",
|
|
11899
|
-
"line":
|
|
11899
|
+
"line": 104,
|
|
11900
11900
|
"origin": "html-text",
|
|
11901
11901
|
"confidence": "certain"
|
|
11902
11902
|
},
|
|
@@ -12836,6 +12836,15 @@
|
|
|
12836
12836
|
"origin": "js-notice",
|
|
12837
12837
|
"confidence": "certain"
|
|
12838
12838
|
},
|
|
12839
|
+
{
|
|
12840
|
+
"id": "70383b194ec0",
|
|
12841
|
+
"surface": "builders-hall",
|
|
12842
|
+
"text": "Sort by",
|
|
12843
|
+
"file": "modules/hall-ui/public/modules.html",
|
|
12844
|
+
"line": 87,
|
|
12845
|
+
"origin": "html-text",
|
|
12846
|
+
"confidence": "certain"
|
|
12847
|
+
},
|
|
12839
12848
|
{
|
|
12840
12849
|
"id": "e0767e80206c",
|
|
12841
12850
|
"surface": "builders-hall",
|
|
@@ -14987,6 +14996,15 @@
|
|
|
14987
14996
|
"origin": "html-text",
|
|
14988
14997
|
"confidence": "certain"
|
|
14989
14998
|
},
|
|
14999
|
+
{
|
|
15000
|
+
"id": "2850b51235fd",
|
|
15001
|
+
"surface": "builders-hall",
|
|
15002
|
+
"text": "Two different bills, one column each. The first is what a project costs this platform. The second is an estimate of what its owner pays their own hosting provider, which bills them directly. A project with no recorded plan reads \"not priced yet\", never $0, and is left out of the total. A self-hosted project runs on its owner's own machine, so its bill is not visible to us.",
|
|
15003
|
+
"file": "modules/hall-ui/public/fleet.html",
|
|
15004
|
+
"line": 39,
|
|
15005
|
+
"origin": "html-text",
|
|
15006
|
+
"confidence": "certain"
|
|
15007
|
+
},
|
|
14990
15008
|
{
|
|
14991
15009
|
"id": "4a25dba3ef56",
|
|
14992
15010
|
"surface": "builders-hall",
|
|
@@ -17710,7 +17728,7 @@
|
|
|
17710
17728
|
"surface": "builders-hall",
|
|
17711
17729
|
"text": "not measured yet",
|
|
17712
17730
|
"file": "modules/hall-ui/public/modules.js",
|
|
17713
|
-
"line":
|
|
17731
|
+
"line": 252,
|
|
17714
17732
|
"origin": "js-markup",
|
|
17715
17733
|
"confidence": "certain"
|
|
17716
17734
|
},
|
|
@@ -18313,7 +18331,7 @@
|
|
|
18313
18331
|
"surface": "builders-hall",
|
|
18314
18332
|
"text": "strong at {…}",
|
|
18315
18333
|
"file": "modules/hall-ui/public/modules.js",
|
|
18316
|
-
"line":
|
|
18334
|
+
"line": 241,
|
|
18317
18335
|
"origin": "js-markup",
|
|
18318
18336
|
"confidence": "certain"
|
|
18319
18337
|
},
|
|
@@ -18952,7 +18970,7 @@
|
|
|
18952
18970
|
"surface": "builders-hall",
|
|
18953
18971
|
"text": "weak at {…}",
|
|
18954
18972
|
"file": "modules/hall-ui/public/modules.js",
|
|
18955
|
-
"line":
|
|
18973
|
+
"line": 243,
|
|
18956
18974
|
"origin": "js-markup",
|
|
18957
18975
|
"confidence": "certain"
|
|
18958
18976
|
},
|
|
@@ -19397,6 +19415,15 @@
|
|
|
19397
19415
|
"origin": "js-text-assign",
|
|
19398
19416
|
"confidence": "certain"
|
|
19399
19417
|
},
|
|
19418
|
+
{
|
|
19419
|
+
"id": "92469c4757f1",
|
|
19420
|
+
"surface": "builders-hall",
|
|
19421
|
+
"text": "{…} not measured yet",
|
|
19422
|
+
"file": "modules/hall-ui/public/modules.js",
|
|
19423
|
+
"line": 226,
|
|
19424
|
+
"origin": "js-markup",
|
|
19425
|
+
"confidence": "certain"
|
|
19426
|
+
},
|
|
19400
19427
|
{
|
|
19401
19428
|
"id": "73c1372b43d9",
|
|
19402
19429
|
"surface": "builders-hall",
|
|
@@ -19609,7 +19636,7 @@
|
|
|
19609
19636
|
"surface": "builders-hall",
|
|
19610
19637
|
"text": "{…} {…} — how-to",
|
|
19611
19638
|
"file": "modules/hall-ui/public/modules.js",
|
|
19612
|
-
"line":
|
|
19639
|
+
"line": 544,
|
|
19613
19640
|
"origin": "js-text-assign",
|
|
19614
19641
|
"confidence": "certain"
|
|
19615
19642
|
},
|
|
@@ -19681,7 +19708,7 @@
|
|
|
19681
19708
|
"surface": "builders-hall",
|
|
19682
19709
|
"text": "{…} — how to use it",
|
|
19683
19710
|
"file": "modules/hall-ui/public/modules.js",
|
|
19684
|
-
"line":
|
|
19711
|
+
"line": 546,
|
|
19685
19712
|
"origin": "js-text-assign",
|
|
19686
19713
|
"confidence": "certain"
|
|
19687
19714
|
},
|
|
@@ -19816,7 +19843,7 @@
|
|
|
19816
19843
|
"surface": "builders-hall",
|
|
19817
19844
|
"text": "· version",
|
|
19818
19845
|
"file": "modules/hall-ui/public/modules.js",
|
|
19819
|
-
"line":
|
|
19846
|
+
"line": 549,
|
|
19820
19847
|
"origin": "js-markup",
|
|
19821
19848
|
"confidence": "certain"
|
|
19822
19849
|
},
|
|
@@ -20131,7 +20158,7 @@
|
|
|
20131
20158
|
"surface": "builders-hall",
|
|
20132
20159
|
"text": "← All modules",
|
|
20133
20160
|
"file": "modules/hall-ui/public/modules.html",
|
|
20134
|
-
"line":
|
|
20161
|
+
"line": 101,
|
|
20135
20162
|
"origin": "html-text",
|
|
20136
20163
|
"confidence": "certain"
|
|
20137
20164
|
},
|
|
@@ -20630,6 +20657,15 @@
|
|
|
20630
20657
|
"origin": "html-text",
|
|
20631
20658
|
"confidence": "certain"
|
|
20632
20659
|
},
|
|
20660
|
+
{
|
|
20661
|
+
"id": "437ddce8e760",
|
|
20662
|
+
"surface": "landing",
|
|
20663
|
+
"text": "A project is a record here and a database of its own. The record holds its name, the GitHub repository it ships to, its web address, how it is hosted, who owns it, when it was created, what state it is in, and its settings — who can see it and how people join. The project's own database holds the same kinds of records as above for the people who build on it: accounts, sessions, tasks, grades, {{currency}}.",
|
|
20664
|
+
"file": "modules/public-landing/public/privacy.html",
|
|
20665
|
+
"line": 108,
|
|
20666
|
+
"origin": "html-text",
|
|
20667
|
+
"confidence": "certain"
|
|
20668
|
+
},
|
|
20633
20669
|
{
|
|
20634
20670
|
"id": "c3504a900b0f",
|
|
20635
20671
|
"surface": "landing",
|
|
@@ -21530,6 +21566,15 @@
|
|
|
21530
21566
|
"origin": "html-text",
|
|
21531
21567
|
"confidence": "certain"
|
|
21532
21568
|
},
|
|
21569
|
+
{
|
|
21570
|
+
"id": "032693d19430",
|
|
21571
|
+
"surface": "landing",
|
|
21572
|
+
"text": "Each {{productName}} project you build in reports a summary of your work there to the platform: the {{currency}} you earned, the works you shipped, your karma, the rank that project gave you, the roles you worked in, and when you were last active. The platform adds these up across every project into one cross-project record. Projects report this themselves — the platform does not read their databases.",
|
|
21573
|
+
"file": "modules/public-landing/public/terms.html",
|
|
21574
|
+
"line": 116,
|
|
21575
|
+
"origin": "html-text",
|
|
21576
|
+
"confidence": "certain"
|
|
21577
|
+
},
|
|
21533
21578
|
{
|
|
21534
21579
|
"id": "9a4a940d2a56",
|
|
21535
21580
|
"surface": "landing",
|
|
@@ -21638,6 +21683,15 @@
|
|
|
21638
21683
|
"origin": "html-text",
|
|
21639
21684
|
"confidence": "certain"
|
|
21640
21685
|
},
|
|
21686
|
+
{
|
|
21687
|
+
"id": "e14fd6120fc6",
|
|
21688
|
+
"surface": "landing",
|
|
21689
|
+
"text": "Extras are the optional parts a project can run — extra AI agents, a Discord mirror, and the rest. You picked a set when you created the project, or took the suggested set by skipping that step; this is where you change your mind. Switching one on or off saves straight away and changes nothing that is already running: nothing restarts, and no work is lost either way. The parts every project runs — the platform itself, the way it tracks work, the builders’ hall — were never part of the choice, so they are not listed here and cannot be switched off.",
|
|
21690
|
+
"file": "modules/public-landing/public/projects.html",
|
|
21691
|
+
"line": 1334,
|
|
21692
|
+
"origin": "html-text",
|
|
21693
|
+
"confidence": "certain"
|
|
21694
|
+
},
|
|
21641
21695
|
{
|
|
21642
21696
|
"id": "7c8dcf228e70",
|
|
21643
21697
|
"surface": "landing",
|
|
@@ -21962,6 +22016,15 @@
|
|
|
21962
22016
|
"origin": "html-text",
|
|
21963
22017
|
"confidence": "certain"
|
|
21964
22018
|
},
|
|
22019
|
+
{
|
|
22020
|
+
"id": "5a2650d439ce",
|
|
22021
|
+
"surface": "landing",
|
|
22022
|
+
"text": "How this project is listed — the kind shown beside its name on the map, in the table and on its card. It is a declaration about the project, not a setting the project obeys: nothing is pushed to it and nothing restarts. One thing does follow the kind: if you never picked your extras yourself, they are the set this kind suggests, so changing the kind changes them too — you will be told when that happens. Extras you picked for yourself are stored and never move. Not Sure is a real answer, and it is the way back if you would rather not say.",
|
|
22023
|
+
"file": "modules/public-landing/public/projects.html",
|
|
22024
|
+
"line": 1314,
|
|
22025
|
+
"origin": "html-text",
|
|
22026
|
+
"confidence": "certain"
|
|
22027
|
+
},
|
|
21965
22028
|
{
|
|
21966
22029
|
"id": "a86a02b0ded9",
|
|
21967
22030
|
"surface": "landing",
|
|
@@ -24338,6 +24401,15 @@
|
|
|
24338
24401
|
"origin": "html-text",
|
|
24339
24402
|
"confidence": "certain"
|
|
24340
24403
|
},
|
|
24404
|
+
{
|
|
24405
|
+
"id": "82d751a27370",
|
|
24406
|
+
"surface": "landing",
|
|
24407
|
+
"text": "The platform first gives this project its own read-only deploy key and switches its deploys over to it, and only then makes the repository private — in that order, so no deploy ever tries to read a private repository with a key that can’t. The change is made with your connected GitHub account, so that account needs admin rights on the repository. It works for a project on a Cloud host; a project on your own host is yours to change on GitHub directly. You can make it public again from here at any time.",
|
|
24408
|
+
"file": "modules/public-landing/public/projects.html",
|
|
24409
|
+
"line": 1242,
|
|
24410
|
+
"origin": "html-text",
|
|
24411
|
+
"confidence": "certain"
|
|
24412
|
+
},
|
|
24341
24413
|
{
|
|
24342
24414
|
"id": "4fd8f5746cc5",
|
|
24343
24415
|
"surface": "landing",
|
|
@@ -24347,6 +24419,15 @@
|
|
|
24347
24419
|
"origin": "html-text",
|
|
24348
24420
|
"confidence": "certain"
|
|
24349
24421
|
},
|
|
24422
|
+
{
|
|
24423
|
+
"id": "768a6990ebfc",
|
|
24424
|
+
"surface": "landing",
|
|
24425
|
+
"text": "The platform stores the date you accepted these terms, and which version, on your account. It is written when you sign in to a project in your browser with your platform account, and only once — signing in again does not change the date you accepted. Signing in from the command line does not record it: you approve that sign-in on GitHub’s page, where these terms are not shown, so an account that has only signed in that way stays unpublished until you sign in to a project in your browser once. This is version",
|
|
24426
|
+
"file": "modules/public-landing/public/terms.html",
|
|
24427
|
+
"line": 120,
|
|
24428
|
+
"origin": "html-text",
|
|
24429
|
+
"confidence": "certain"
|
|
24430
|
+
},
|
|
24350
24431
|
{
|
|
24351
24432
|
"id": "20fcebaa85c4",
|
|
24352
24433
|
"surface": "landing",
|
|
@@ -24500,6 +24581,15 @@
|
|
|
24500
24581
|
"origin": "html-text",
|
|
24501
24582
|
"confidence": "certain"
|
|
24502
24583
|
},
|
|
24584
|
+
{
|
|
24585
|
+
"id": "a1aa7835abce",
|
|
24586
|
+
"surface": "landing",
|
|
24587
|
+
"text": "This is a list of which variables your project needs and what each one is for — not the secrets themselves. The values belong wherever your project actually runs (Vercel, Netlify, Render, or your own machine): that is where the running app reads them, and it already keeps them encrypted, logs who touched them and lets you rotate them. Keeping a second copy here would make this platform the keeper of your credentials and buy you nothing.",
|
|
24588
|
+
"file": "modules/public-landing/public/projects.html",
|
|
24589
|
+
"line": 1349,
|
|
24590
|
+
"origin": "html-text",
|
|
24591
|
+
"confidence": "certain"
|
|
24592
|
+
},
|
|
24503
24593
|
{
|
|
24504
24594
|
"id": "d83b739afb1e",
|
|
24505
24595
|
"surface": "landing",
|
|
@@ -24590,6 +24680,15 @@
|
|
|
24590
24680
|
"origin": "html-text",
|
|
24591
24681
|
"confidence": "certain"
|
|
24592
24682
|
},
|
|
24683
|
+
{
|
|
24684
|
+
"id": "50f764cf1229",
|
|
24685
|
+
"surface": "landing",
|
|
24686
|
+
"text": "Two things, and only two: a name — this project already has one — and a description of what it is. Modules, artwork, a finished setup interview: none of them are required, because the bar is there to keep empty shells off the map, not to make you finish anything. Until it is met the project is not listed publicly and nobody can ask to join it; the project itself runs exactly the same either way. Adding a description puts it on the map, and clearing one takes it back off.",
|
|
24687
|
+
"file": "modules/public-landing/public/projects.html",
|
|
24688
|
+
"line": 1214,
|
|
24689
|
+
"origin": "html-text",
|
|
24690
|
+
"confidence": "certain"
|
|
24691
|
+
},
|
|
24593
24692
|
{
|
|
24594
24693
|
"id": "b0c3729108be",
|
|
24595
24694
|
"surface": "landing",
|
|
@@ -24662,6 +24761,15 @@
|
|
|
24662
24761
|
"origin": "html-text",
|
|
24663
24762
|
"confidence": "certain"
|
|
24664
24763
|
},
|
|
24764
|
+
{
|
|
24765
|
+
"id": "f68a38de7e1b",
|
|
24766
|
+
"surface": "landing",
|
|
24767
|
+
"text": "Visitors who aren’t signed in meet a sign-in door instead of the project’s pages — its front page, its status page, and its hall. The door itself stays open, so members can always get in, and members see everything either way. It is separate from the repository’s visibility above: the code on GitHub is its own setting. Changing it restarts the project to pick it up — the line under the choice says what the project is running right now.",
|
|
24768
|
+
"file": "modules/public-landing/public/projects.html",
|
|
24769
|
+
"line": 1258,
|
|
24770
|
+
"origin": "html-text",
|
|
24771
|
+
"confidence": "certain"
|
|
24772
|
+
},
|
|
24665
24773
|
{
|
|
24666
24774
|
"id": "3d6b0bf6c2db",
|
|
24667
24775
|
"surface": "landing",
|
|
@@ -25256,6 +25364,15 @@
|
|
|
25256
25364
|
"origin": "html-text",
|
|
25257
25365
|
"confidence": "certain"
|
|
25258
25366
|
},
|
|
25367
|
+
{
|
|
25368
|
+
"id": "1e6d91f484e4",
|
|
25369
|
+
"surface": "landing",
|
|
25370
|
+
"text": "Your cross-project record is descriptive analytics and never authority. What you may do inside any project is decided by that project alone, from its own records, at the moment you ask. A large record grants nothing and a hidden one takes nothing away; no project is required to read it, and none may treat it as permission. A rank shown here is that project’s own standing for you, as that project reported it — the platform holds no rank of its own.",
|
|
25371
|
+
"file": "modules/public-landing/public/terms.html",
|
|
25372
|
+
"line": 117,
|
|
25373
|
+
"origin": "html-text",
|
|
25374
|
+
"confidence": "certain"
|
|
25375
|
+
},
|
|
25259
25376
|
{
|
|
25260
25377
|
"id": "63535be9eb75",
|
|
25261
25378
|
"surface": "landing",
|
|
@@ -26597,6 +26714,15 @@
|
|
|
26597
26714
|
"origin": "html-text",
|
|
26598
26715
|
"confidence": "certain"
|
|
26599
26716
|
},
|
|
26717
|
+
{
|
|
26718
|
+
"id": "a5319c33053a",
|
|
26719
|
+
"surface": "landing",
|
|
26720
|
+
"text": "— no one can apply: the project’s hall and its sign-in say so, and you invite people by GitHub username from the hall’s Watch page; only an invited person’s sign-in gets in — and people who asked before you switched stay in your queue, to approve or dismiss. Whichever you pick, people who are already members stay members. Changing it restarts the project to pick it up — the line under the choice says what the project is running right now.",
|
|
26721
|
+
"file": "modules/public-landing/public/projects.html",
|
|
26722
|
+
"line": 1273,
|
|
26723
|
+
"origin": "html-text",
|
|
26724
|
+
"confidence": "certain"
|
|
26725
|
+
},
|
|
26600
26726
|
{
|
|
26601
26727
|
"id": "5becfcad07c3",
|
|
26602
26728
|
"surface": "landing",
|
|
@@ -26615,6 +26741,15 @@
|
|
|
26615
26741
|
"origin": "html-text",
|
|
26616
26742
|
"confidence": "certain"
|
|
26617
26743
|
},
|
|
26744
|
+
{
|
|
26745
|
+
"id": "013f0e214b89",
|
|
26746
|
+
"surface": "landing",
|
|
26747
|
+
"text": "— the map shows only that something is there; its name, and everything else about it, stay yours, and nobody can ask to join. Switching to Stealth is itself visible: someone comparing the map before and after can tell which project went quiet. Whichever you pick, a project reaches the map only once it has a name and a description. This is separate from “Who can see it” above — that one is the door on the project’s own pages. Changing it restarts the project to pick it up.",
|
|
26748
|
+
"file": "modules/public-landing/public/projects.html",
|
|
26749
|
+
"line": 1292,
|
|
26750
|
+
"origin": "html-text",
|
|
26751
|
+
"confidence": "certain"
|
|
26752
|
+
},
|
|
26618
26753
|
{
|
|
26619
26754
|
"id": "b5bac008ba11",
|
|
26620
26755
|
"surface": "landing",
|
|
@@ -3143,5 +3143,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
3143
3143
|
landed since 1.21.151 with no explicit bump. run 39671625798. (task 1002620)
|
|
3144
3144
|
1.21.153 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3145
3145
|
landed since 1.21.152 with no explicit bump. run 39675693737. (task 1002620)
|
|
3146
|
+
1.21.154 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3147
|
+
landed since 1.21.153 with no explicit bump. run 39800316919. (task 1002620)
|
|
3148
|
+
1.21.155 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3149
|
+
landed since 1.21.154 with no explicit bump. run 39805364072. (task 1002620)
|
|
3146
3150
|
---------------------------------------------------------------------------
|
|
3147
3151
|
```
|
package/docs/modules-contract.md
CHANGED
|
@@ -393,6 +393,7 @@ Run `bongos upgrade` to confirm coreVersion compatibility, then `node scripts/gd
|
|
|
393
393
|
- **A how-to is required** ([ADR 0347](adr/0347-every-store-module-ships-a-how-to.md)). `modules/<key>/HOWTO.md` is what a buyer reads — the store shows it as the module's page — so it is written for the person who installs the module, not for an AI working inside it (that is `CLAUDE.md`). It is plain Markdown: any AI or person can write it. Publish refuses the version unless it has these five level-2 headings, in any order and any case, each with some text under it: `## What it does`, `## Install and enable`, `## How to use it` (with one worked example), `## Configuration` ("None." is fine) and `## Limits and known issues` ("None known." is fine). HTML comments don't count as text, so the scaffold's prompts must be replaced. The refusal names each failing section. The check is one function, `checkHowto` in `scripts/gds/module-artifact.js`; the CLI runs it before uploading and the store runs it again on upload, so a hand-built upload can't skip it. `bongos module check` reports it as advice only — an upstream submit is not gated by it. Install and update don't re-check it, so a version published before the gate still installs. The file travels in the tarball, so its hash pins it to the version. An optional `howto.artifactUrl` in `module.json` (an `https://` link on `claude.ai`) is shown as an extra, never graded.
|
|
394
394
|
- **Getting listed** (task 1003807, [ADR 0343](adr/0343-a-module-score-is-a-security-gate-then-an-average-of-visible-parts.md)). Publishing a version does not by itself put it in the store's catalog, `GET /store/modules`. The catalog shows each module's newest version, judged by its current score. It must pass the Security gate first; a version that failed it, or has not been checked yet, is not listed. A new version with no install or reliability data yet is listed with a **New** label and is not ranked; the floor does not apply to it until it has a real score. Every other version is listed only if its overall score is **at least 50 out of 100**. Below that it is not listed at all. The floor is fixed in Bongos itself (`QUALITY_FLOOR` in `src/bongos/module-listing.js`) and returned in the catalog response; no author or instance setting moves it, and changing it is an owner-approved, reviewed task.
|
|
395
395
|
- **What a module is strong and weak at** (task 1003799, ADR 0343 D4). Each catalog entry also carries `parts` (the current result of Tests, Clean installs, Reliability, Tester feedback and How-to) and a reading of them: `strengths` (a part scored **80 or more**), `weaknesses` (a part scored **below the floor**) and `unmeasured` (a part with no score yet, which is never counted as weak). Each strength and weakness has a one-sentence `detail` saying what the number rests on. Security is not among them: every listed version has passed it. The reading is `readParts` in `src/bongos/module-listing.js`; the hall's Modules tab shows it in its "In the store" group, so two modules with the same overall score can be told apart.
|
|
396
|
+
- **Sorting by a part** (task 1003800). `GET /store/modules?sort=<part>` orders the listed modules by one part a buyer cares about: `tests`, `install`, `reliability`, `tester_feedback` or `docs` (the response lists them as `sort_parts`, and says which one it applied as `sort`). Modules with a score for that part come first, highest first; a tie goes to the higher overall score, then the module key. A module with no score for that part goes last, so missing data never wins or loses a place on its own. New modules are not sorted: they are never ranked. Any other `sort` value is refused with a 400. Without `sort`, both lists are in key order. The rule is `sortByPart` in `src/bongos/module-listing.js`.
|
|
396
397
|
|
|
397
398
|
### 7. Install from the store
|
|
398
399
|
|
package/docs/page-readings.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"adr": "0341 D3",
|
|
6
6
|
"reread": "node scripts/gds/page-reader.js --stale",
|
|
7
7
|
"how": ["Generated by node scripts/gds/page-reader.js (BV2.TW04, task 1004315; ADR 0341 D3). Do not hand-edit.","One entry per page of docs/page-inventory.json. Lines are in page order: the default state first, and a line only another state shows sits where that state shows it, with its state named.","placement: placed = a docs/copy-registry.json row renders it (file, line, string_id); shared = shell text every page of the surface carries (top bar, sidebar, footer), with its row when the registry has one; unplaced = the registry cannot place it (a rewrite becomes an engineer task, ADR 0341 D4).","text keeps {…} where the registry row has a hole, or where a value the page read from its API was filled in. A string that is only such data is counted under omitted.data, not listed.","reading_hash is over the non-shared lines (key, section, text); files_hash is over the page's inventory files. --check compares files_hash only and never opens a browser.","Rendered through the hall-preview harness (hall) and the ui-design kit stub (landing, status), at 1280x800 with the clock pinned, so a reading is the fixture world's page."],
|
|
8
|
-
"counts": {"pages":46,"lines":
|
|
8
|
+
"counts": {"pages":46,"lines":5563,"placed":1707,"shared":398,"unplaced":3458,"omitted_data":3605},
|
|
9
9
|
"pages": [
|
|
10
10
|
{
|
|
11
11
|
"id": "builders:atlas",
|
|
@@ -1885,10 +1885,10 @@
|
|
|
1885
1885
|
"surface": "builders",
|
|
1886
1886
|
"title": "Modules",
|
|
1887
1887
|
"states_read": ["browse","search-empty","lens","details","out"],
|
|
1888
|
-
"files_hash": "
|
|
1889
|
-
"reading_hash": "
|
|
1890
|
-
"counts": {"lines":
|
|
1891
|
-
"omitted": {"data":
|
|
1888
|
+
"files_hash": "78b02310ae1e8e04",
|
|
1889
|
+
"reading_hash": "a3861c8a1816328f",
|
|
1890
|
+
"counts": {"lines":57,"placed":25,"shared":8,"unplaced":24},
|
|
1891
|
+
"omitted": {"data":105},
|
|
1892
1892
|
"notes": ["details: an action failed (page.click: Timeout 6000ms exceeded.); read as it stood"],
|
|
1893
1893
|
"lines": [
|
|
1894
1894
|
{"key":"L0001","section":"skip link","text":"Skip to content","placement":"shared","file":"modules/hall-ui/public/shell.js","line":872,"string_id":"87cee78ca134"},
|
|
@@ -1931,21 +1931,23 @@
|
|
|
1931
1931
|
{"key":"L0038","section":"Module catalog","text":"submit for review","placement":"placed","file":"modules/hall-ui/public/modules.js","line":187,"string_id":"0215b2cdca8c"},
|
|
1932
1932
|
{"key":"L0039","section":"Module catalog","text":"A module built here can be submitted upstream for review, so it can join the shared catalog with your name and this project credited.","placement":"placed","file":"modules/hall-ui/public/modules.html","line":74,"string_id":"2e17d7e236d9"},
|
|
1933
1933
|
{"key":"L0040","section":"Module catalog","text":"In the store","placement":"placed","file":"modules/hall-ui/public/modules.html","line":83,"string_id":"ecfebcd52894"},
|
|
1934
|
-
{"key":"L0041","section":"Module catalog","text":"
|
|
1935
|
-
{"key":"L0042","section":"Module catalog","text":"
|
|
1936
|
-
{"key":"L0043","section":"Module catalog","text":"
|
|
1937
|
-
{"key":"L0044","section":"Module catalog","text":"
|
|
1938
|
-
{"key":"L0045","section":"Module catalog","text":"
|
|
1939
|
-
{"key":"L0046","section":"
|
|
1940
|
-
{"key":"L0047","section":"Module catalog","text":"
|
|
1941
|
-
{"key":"L0048","section":"
|
|
1942
|
-
{"key":"L0049","section":"
|
|
1943
|
-
{"key":"L0050","section":"What are you doing now?","text":"
|
|
1944
|
-
{"key":"L0051","section":"What are you doing now?","text":"
|
|
1945
|
-
{"key":"L0052","section":"What are you doing now?","text":"
|
|
1946
|
-
{"key":"L0053","section":"What are you doing now?","text":"
|
|
1947
|
-
{"key":"L0054","section":"What are you doing now?","text":"
|
|
1948
|
-
{"key":"L0055","section":"What are you doing now?","text":"
|
|
1934
|
+
{"key":"L0041","section":"Module catalog","text":"Sort by","placement":"placed","file":"modules/hall-ui/public/modules.html","line":87,"string_id":"70383b194ec0"},
|
|
1935
|
+
{"key":"L0042","section":"Module catalog","text":"Name","placement":"unplaced"},
|
|
1936
|
+
{"key":"L0043","section":"Module catalog","text":"No store module matches that {…}.","placement":"unplaced","state":"search-empty"},
|
|
1937
|
+
{"key":"L0044","section":"Module catalog","text":"scores","placement":"unplaced","occurrences":2},
|
|
1938
|
+
{"key":"L0045","section":"Module catalog","text":"strong at {…}","placement":"placed","file":"modules/hall-ui/public/modules.js","line":241,"string_id":"e294c3429c2e","occurrences":3},
|
|
1939
|
+
{"key":"L0046","section":"Module catalog","text":"weak at {…}","placement":"placed","file":"modules/hall-ui/public/modules.js","line":243,"string_id":"20318b6da94e"},
|
|
1940
|
+
{"key":"L0047","section":"Module catalog","text":"A part is strong at 80 out of 100 or more, and weak below the listing floor. A part with no data yet is not counted against a module. Sort by a part to see the modules strongest at it first; a module with no score for that part goes last, and a new module is never ranked.","placement":"placed","file":"modules/hall-ui/public/modules.html","line":90,"string_id":"e395cd11edab"},
|
|
1941
|
+
{"key":"L0048","section":"footer","text":"Sign out","placement":"shared","file":"modules/hall-ui/public/shell.js","line":520,"string_id":"1883ad7f07fc"},
|
|
1942
|
+
{"key":"L0049","section":"Module catalog","text":"Builders hall · this session","placement":"placed","file":"modules/hall-ui/public/craft-mode.js","line":810,"string_id":"fd1903586e8e"},
|
|
1943
|
+
{"key":"L0050","section":"What are you doing now?","text":"What are you doing now?","placement":"placed","file":"modules/hall-ui/public/craft-mode.js","line":811,"string_id":"60853319f290"},
|
|
1944
|
+
{"key":"L0051","section":"What are you doing now?","text":"Pick one. You can switch any time from the top bar.","placement":"placed","file":"modules/hall-ui/public/craft-mode.js","line":812,"string_id":"4f87d5b17b54"},
|
|
1945
|
+
{"key":"L0052","section":"What are you doing now?","text":"Building","placement":"unplaced"},
|
|
1946
|
+
{"key":"L0053","section":"What are you doing now?","text":"{…} and {…}","placement":"placed","file":"modules/hall-ui/public/profile-nudge.js","line":77,"string_id":"56b00d773232","occurrences":3},
|
|
1947
|
+
{"key":"L0054","section":"What are you doing now?","text":"Artistry","placement":"unplaced"},
|
|
1948
|
+
{"key":"L0055","section":"What are you doing now?","text":"Ideating","placement":"unplaced"},
|
|
1949
|
+
{"key":"L0056","section":"What are you doing now?","text":"Turn thoughts into {…}.","placement":"unplaced"},
|
|
1950
|
+
{"key":"L0057","section":"What are you doing now?","text":"Ask me again next session","placement":"placed","file":"modules/hall-ui/public/craft-mode.js","line":815,"string_id":"fa86bf403775"}
|
|
1949
1951
|
]
|
|
1950
1952
|
},
|
|
1951
1953
|
{
|
|
@@ -82,9 +82,12 @@
|
|
|
82
82
|
<div class="ov-group__head">
|
|
83
83
|
<span class="ov-group__name">In the store</span>
|
|
84
84
|
<span class="ov-group__n" id="store-n"></span>
|
|
85
|
+
<!-- task 1003800: the buyer picks the part that matters to them, and
|
|
86
|
+
the server orders by it (sortByPart). Filled from sort_parts. -->
|
|
87
|
+
<label class="ov-group__note">Sort by <select id="store-sort"><option value="">Name</option></select></label>
|
|
85
88
|
</div>
|
|
86
89
|
<ul class="ov-rows" id="store-grid"></ul>
|
|
87
|
-
<p class="ov-foot" id="store-lede">A part is strong at 80 out of 100 or more, and weak below the listing floor. A part with no data yet is not counted against a module.</p>
|
|
90
|
+
<p class="ov-foot" id="store-lede">A part is strong at 80 out of 100 or more, and weak below the listing floor. A part with no data yet is not counted against a module. Sort by a part to see the modules strongest at it first; a module with no score for that part goes last, and a new module is never ranked.</p>
|
|
88
91
|
</div>
|
|
89
92
|
</section>
|
|
90
93
|
|
|
@@ -211,6 +211,20 @@
|
|
|
211
211
|
// short labels; the sentence behind each is one click away in the details, the
|
|
212
212
|
// splitCriterion idea: scannable in a list, thorough on demand.
|
|
213
213
|
let storeModules = [];
|
|
214
|
+
// The part the buyer sorts by (task 1003800): '' is name order. The server owns
|
|
215
|
+
// the order and the list of parts; this page only asks for one and shows it.
|
|
216
|
+
let storeSort = '';
|
|
217
|
+
let storeSortTitle = '';
|
|
218
|
+
let storeSortWired = false;
|
|
219
|
+
|
|
220
|
+
// The sorted-by part's own score, so the order explains itself on every row.
|
|
221
|
+
function sortedPartFact(m) {
|
|
222
|
+
if (!storeSort || m.is_new) return '';
|
|
223
|
+
const p = m.parts && m.parts[storeSort];
|
|
224
|
+
return p && p.score != null
|
|
225
|
+
? `<span class="ov-fact">${escapeHtml(storeSortTitle)} <b>${escapeHtml(String(p.score))}</b></span>`
|
|
226
|
+
: `<span class="ov-fact">${escapeHtml(storeSortTitle)} not measured yet</span>`;
|
|
227
|
+
}
|
|
214
228
|
|
|
215
229
|
function partsList(items) {
|
|
216
230
|
return items.map((p) => `${escapeHtml(p.title)} <b>${escapeHtml(String(p.score))}</b>`).join(', ');
|
|
@@ -220,6 +234,8 @@
|
|
|
220
234
|
const facts = [m.is_new
|
|
221
235
|
? '<span class="fact-pill fact-pill--info" title="No real-world data yet, so it is listed but not ranked.">new</span>'
|
|
222
236
|
: `<span class="ov-fact">scores <b>${escapeHtml(String(m.overall))}</b></span>`];
|
|
237
|
+
const sorted = sortedPartFact(m);
|
|
238
|
+
if (sorted) facts.push(sorted);
|
|
223
239
|
const strong = Array.isArray(m.strengths) ? m.strengths : [];
|
|
224
240
|
const weak = Array.isArray(m.weaknesses) ? m.weaknesses : [];
|
|
225
241
|
if (strong.length) facts.push(`<span class="ov-fact">strong at ${partsList(strong)}</span>`);
|
|
@@ -275,11 +291,26 @@
|
|
|
275
291
|
|
|
276
292
|
// Best-effort and last: the store is a second read, and the modules on disk ARE
|
|
277
293
|
// this page, so a store that cannot be read costs this group and nothing else.
|
|
294
|
+
// Filled and wired once, on the first store read; a re-read only re-renders.
|
|
295
|
+
function fillStoreSort(parts) {
|
|
296
|
+
const select = $('#store-sort');
|
|
297
|
+
if (storeSortWired || !select || !Array.isArray(parts)) return;
|
|
298
|
+
storeSortWired = true;
|
|
299
|
+
for (const p of parts) select.add(new Option(p.title, p.part));
|
|
300
|
+
select.addEventListener('change', () => {
|
|
301
|
+
storeSort = select.value;
|
|
302
|
+
storeSortTitle = storeSort ? select.options[select.selectedIndex].text : '';
|
|
303
|
+
loadStore();
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
278
307
|
async function loadStore() {
|
|
279
308
|
try {
|
|
280
|
-
const
|
|
309
|
+
const q = storeSort ? `?sort=${encodeURIComponent(storeSort)}` : '';
|
|
310
|
+
const res = await api.request('GET', `${API}/store/modules${q}`);
|
|
281
311
|
if (!res.ok) return;
|
|
282
312
|
const body = res.data || {};
|
|
313
|
+
fillStoreSort(body.sort_parts);
|
|
283
314
|
storeModules = [...(body.listed || []), ...(body.new || [])];
|
|
284
315
|
renderStore();
|
|
285
316
|
} catch (err) {
|
|
@@ -12,3 +12,5 @@ Also gone, and the one rule in that list: `.ab-caption` takes the lede's `--meas
|
|
|
12
12
|
**A store version's how-to is a view of the Modules page, not a new page (task 1004366).** `/builders/modules?howto=<key>&version=<X.Y.Z>` hides the catalog and shows that version's `HOWTO.md` in the reading room's article card: the page adds `body.room` so `room.css`'s sizes apply, and the markdown goes through `md-reader.js` (author-written, so every byte is escaped; only absolute http(s), mailto and #anchor links become links). A query, not a `#/` route — the hash namespace is frozen to the idea and blocker overlays. "Save as PDF" is `window.print()` with an `@media print` block in `modules.css` that keeps only the document and prints in the system ink (`CanvasText`), because a literal colour is the token tier's. Harness fixture: `store__modules__howto.json`.
|
|
13
13
|
|
|
14
14
|
**The store's modules are a third group on the same panel, read as strengths and weaknesses (task 1003799, ADR 0343 D4).** `#store-group` ("In the store") lists what `GET /store/modules` lists, hidden until that read answers with something; it loads after the modules on disk and best-effort, so a store that cannot be read costs this group and nothing else. A row is the same `.ov-row`: the overall score as a plain fact (or the `new` info pill), `strong at Tests 96, How-to 88` as a plain fact, and `weak at …` as the warn pill, because a weakness is the exception a buyer must not miss. The sentence behind each part ("Tests scored 96 out of 100, from 40 test cases.") and the parts with no data yet sit in the row's `<details class="mod-more">`, the `splitCriterion` idea: short label in the list, the detail one click away. The reading is the server's (`readParts` in `src/bongos/module-listing.js`: strong at 80 or more, weak below the listing floor, unmeasured never weak); the page re-derives nothing. Harness fixture: `store__modules.json`.
|
|
15
|
+
|
|
16
|
+
**The buyer sorts the store by the part that matters to them (task 1003800, owner decision 2026-10-22).** A "Sort by" menu sits in the store group's head (`#store-sort`, `.ov-group__note`): Name, then the parts the server lists in `sort_parts`. Picking one re-reads `GET /store/modules?sort=<part>`, and the server orders the listed modules (`sortByPart` in `src/bongos/module-listing.js`: highest for that part first, a tie to the overall score then the key, a module with no score for the part last). The page never sorts the rows itself, and New modules keep name order because they are never ranked. While a part is picked, each listed row carries that part's score as a plain fact (`Reliability 91`, or `Reliability not measured yet`), so the order explains itself. The owner chose the buyer over a per-category "key part" because nothing records what a category is for, and a hidden weighting would break the score an author can check (ADR 0343 D3).
|
|
@@ -122,6 +122,12 @@ function foldLiveReadings(readings) {
|
|
|
122
122
|
|
|
123
123
|
// ── the sign-off refusal ladder ─────────────────────────────────────────────
|
|
124
124
|
|
|
125
|
+
// PAUSED (owner, 2026-10-22): the "someone else signs it off" rule below is off,
|
|
126
|
+
// so the person who shipped the work may sign off its UAT/review themselves.
|
|
127
|
+
// Delete this flag to restore the rule. UAT_SELF_SIGNOFF=off turns it back on
|
|
128
|
+
// (the tests do, so the paused rule stays proven while it waits).
|
|
129
|
+
const SELF_SIGNOFF_ALLOWED = process.env.UAT_SELF_SIGNOFF !== 'off';
|
|
130
|
+
|
|
125
131
|
// PURE — may this person sign this criterion off now? Returns null (allowed) or
|
|
126
132
|
// { code, status, message, ...detail }. The ORDER is the order a person would
|
|
127
133
|
// want to be told: is there anything to sign, is it the right kind of sign-off,
|
|
@@ -163,7 +169,7 @@ function signoffRefusal({ criterion, counts, remaining = [], backendOnly, kind,
|
|
|
163
169
|
}
|
|
164
170
|
const signer = String(signerId);
|
|
165
171
|
const isOwner = signerIsOwner === true || (ownerId != null && String(ownerId) === signer);
|
|
166
|
-
if (!isOwner && shipperIds.map(String).includes(signer)) {
|
|
172
|
+
if (!SELF_SIGNOFF_ALLOWED && !isOwner && shipperIds.map(String).includes(signer)) {
|
|
167
173
|
return { code: 'signer_shipped_this_work', status: 403, message: 'You shipped work linked to this criterion, so someone else has to sign it off. Any other reviewer, or the project owner, can.' };
|
|
168
174
|
}
|
|
169
175
|
if (kind === 'uat' && !recording) {
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.155",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.21.
|
|
9
|
+
"version": "1.21.155",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.155",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|