@bongos/core 1.19.998 → 1.19.1000

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 (86) hide show
  1. package/.bongos-core.json +105 -90
  2. package/.claude/skills/collab-review/SKILL.md +24 -13
  3. package/clients/bongos-client/README.md +1 -1
  4. package/clients/bongos-client/bongos-client.global.js +4 -0
  5. package/clients/bongos-client/index.cjs +4 -0
  6. package/clients/bongos-client/index.d.ts +7 -0
  7. package/clients/bongos-client/index.mjs +4 -0
  8. package/docs/adr/0330-an-ask-is-answered-where-it-was-asked.md +155 -0
  9. package/docs/adr/README.md +1 -0
  10. package/docs/api/openapi.json +154 -4
  11. package/docs/api-reference.md +5 -3
  12. package/docs/copy-inventory.md +18 -13
  13. package/docs/copy-registry.json +70 -15
  14. package/docs/module-api-changelog.md +4 -0
  15. package/modules/hall-ui/public/collab-lib.js +79 -0
  16. package/modules/hall-ui/public/collab.css +60 -0
  17. package/modules/hall-ui/public/collab.js +134 -5
  18. package/modules/lifecycle/help-requests.js +118 -8
  19. package/modules/lifecycle/migrations/lifecycle_011_help_request_replies.sql +113 -0
  20. package/modules/lifecycle/routes/help-requests.js +93 -13
  21. package/modules/provisioning/capacity.js +3 -3
  22. package/modules/provisioning/control-plane-guard.js +1 -1
  23. package/modules/provisioning/core-upgrade.js +7 -7
  24. package/modules/provisioning/migrations/provisioning_027_cloud_host_shape_rename.sql +58 -0
  25. package/modules/provisioning/onboard-plan.js +1 -1
  26. package/modules/provisioning/paid-shape-gate.js +28 -15
  27. package/modules/provisioning/provisioning.js +18 -14
  28. package/modules/provisioning/routes/repo-private.js +1 -1
  29. package/modules/provisioning/tests/liveness.mjs +16 -8
  30. package/modules/provisioning/tests/provisioning.mjs +1 -1
  31. package/modules/public-landing/public/projects.html +26 -27
  32. package/modules/ui-design/kit/fixtures/provisioning-instances.json +1 -1
  33. package/package-lock.json +2 -2
  34. package/package.json +1 -1
  35. package/scripts/gds/init.js +12 -4
  36. package/scripts/gds/onboard.js +1 -1
  37. package/scripts/gds/provision-capacity.js +6 -1
  38. package/scripts/gds/provision-config.js +6 -3
  39. package/scripts/gds/provision-core-upgrade.js +8 -8
  40. package/scripts/gds/provision-disconnect.js +2 -2
  41. package/scripts/gds/provision-process.js +2 -2
  42. package/scripts/gds/provision-repo-private.js +1 -1
  43. package/scripts/gds/provision-repo.js +13 -3
  44. package/scripts/gds/provision-teardown.js +2 -2
  45. package/scripts/gds/provision-units.js +2 -2
  46. package/scripts/gds/provision.js +6 -6
  47. package/src/module-api.js +1 -1
  48. package/tests/collab_page.mjs +140 -7
  49. package/tests/core_upgrade_door.mjs +1 -1
  50. package/tests/core_upgrade_runner.mjs +20 -20
  51. package/tests/deploy_page_projects.mjs +5 -5
  52. package/tests/hall_collab_world.mjs +6 -2
  53. package/tests/help_requests.mjs +201 -6
  54. package/tests/hub_disconnect_ui.mjs +4 -1
  55. package/tests/init.mjs +6 -6
  56. package/tests/onboard.mjs +5 -4
  57. package/tests/project_catalog_backfill.mjs +1 -1
  58. package/tests/project_catalog_bridge.mjs +2 -2
  59. package/tests/project_catalog_routes.mjs +4 -4
  60. package/tests/projects_hub.mjs +1 -1
  61. package/tests/projects_hub_pre_uat.mjs +22 -5
  62. package/tests/projects_hub_repo_private.mjs +1 -1
  63. package/tests/provision.mjs +32 -32
  64. package/tests/provision_byo_host.mjs +1 -1
  65. package/tests/provision_caddy_wiring.mjs +1 -1
  66. package/tests/provision_disconnect.mjs +3 -3
  67. package/tests/provision_repo_private.mjs +1 -1
  68. package/tests/provision_restart.mjs +5 -5
  69. package/tests/provision_settings_apply.mjs +4 -4
  70. package/tests/provision_teardown_address.mjs +2 -2
  71. package/tests/provisioning_capacity.mjs +40 -34
  72. package/tests/provisioning_capacity_gate.mjs +5 -12
  73. package/tests/provisioning_default_domain.mjs +1 -1
  74. package/tests/provisioning_domain_attach.mjs +4 -4
  75. package/tests/provisioning_domain_unique.mjs +2 -2
  76. package/tests/provisioning_error_note_scope.mjs +1 -1
  77. package/tests/provisioning_module_selection.mjs +5 -5
  78. package/tests/provisioning_onboard_mode.mjs +2 -2
  79. package/tests/provisioning_paid_shape_gate.mjs +57 -44
  80. package/tests/provisioning_repo_private_route.mjs +1 -1
  81. package/tests/provisioning_restart.mjs +11 -4
  82. package/tests/provisioning_settings_apply.mjs +12 -5
  83. package/tests/provisioning_settings_env.mjs +1 -1
  84. package/tests/provisioning_teardown_intent.mjs +3 -3
  85. package/tests/public_landing_projects.mjs +13 -6
  86. package/tests/upgrade.mjs +2 -2
@@ -4,13 +4,13 @@
4
4
  > Deterministic on a given tree — regenerate and commit rather than hand-editing.
5
5
  > Machine-readable twin: [`copy-registry.json`](copy-registry.json).
6
6
 
7
- **1933 strings** across 3 surfaces · 1673 distinct pieces of copy · 1933 certain, 0 heuristic · 178 shown in more than one place.
7
+ **1938 strings** across 3 surfaces · 1677 distinct pieces of copy · 1938 certain, 0 heuristic · 179 shown in more than one place.
8
8
 
9
9
  ## Surfaces
10
10
 
11
11
  | surface | lives at | files | strings |
12
12
  |---|---|---|---|
13
- | `builders-hall` | `modules/hall-ui/public` | 97 | 1442 |
13
+ | `builders-hall` | `modules/hall-ui/public` | 97 | 1447 |
14
14
  | `status-dashboard` | `modules/status-ui/public` | 4 | 100 |
15
15
  | `landing` | `modules/public-landing/public` | 5 | 391 |
16
16
 
@@ -76,9 +76,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
76
76
  | `cc5106af4b35` | 3x | {…} of {…} criteria satisfied | modules/hall-ui/public/goals-lib.js:32, modules/hall-ui/public/goals-render.js:705, modules/hall-ui/public/goals.js:45 |
77
77
  | `7926e30955d2` | 3x | ← Back to goal | modules/hall-ui/public/goals.html:199, modules/hall-ui/public/goals.html:210, modules/hall-ui/public/goals.html:222 |
78
78
  | `07f422cbdb7e` | 2x | ) and capture-resistant by design. | modules/public-landing/public/projects.html:1026, modules/public-landing/public/projects.html:1053 |
79
- | … | | _138 more in the JSON registry_ | |
79
+ | … | | _139 more in the JSON registry_ | |
80
80
 
81
- ## `builders-hall` — 1442 strings
81
+ ## `builders-hall` — 1447 strings
82
82
 
83
83
  | id | conf | text | where |
84
84
  |---|---|---|---|
@@ -182,7 +182,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
182
182
  | `5fcfdf8975cf` | certain | As configuration: | `modules/hall-ui/public/government.js:829` |
183
183
  | `01a0f29ff406` | certain | As first filed | `modules/hall-ui/public/idea.js:439` |
184
184
  | `688cc6dd38ee` | certain | Asked of you | `modules/hall-ui/public/collab.html:48` |
185
- | `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/collab.js:84` |
185
+ | `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/collab.js:91` |
186
186
  | `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/watch.js:488` |
187
187
  | `8c8ec2597036` | certain | Assigned {…} to builder {…}. | `modules/hall-ui/public/government.js:463` |
188
188
  | `46714066f2da` | certain | Audit log | `modules/hall-ui/public/watch.html:141` |
@@ -263,6 +263,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
263
263
  | `e712dd69a5f6` | certain | Clone the project to your machine, or open your hosted dev box (where it is already cloned). The build command | `modules/hall-ui/public/hall-render.js:953` |
264
264
  | `f42cb1edcf1e` | certain | Clone the repository | `modules/hall-ui/public/hall-render.js:864` |
265
265
  | `70f6a704d504` | certain | Close it | `modules/hall-ui/public/copy-desk.html:140` |
266
+ | `b16bd3e36632` | certain | Close this ask | `modules/hall-ui/public/collab.js:263` |
266
267
  | `d12a2fb5730d` | certain | Close this flag | `modules/hall-ui/public/copy-desk.html:116` |
267
268
  | `3d148e19e03a` | certain | Closed. | `modules/hall-ui/public/copy-desk.js:510` |
268
269
  | `2654dc3ded21` | certain | Closing is a judgement too — say what you decided, so the next person does not re-litigate it. | `modules/hall-ui/public/copy-desk.js:495` |
@@ -278,13 +279,13 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
278
279
  | `c07898571b24` | certain | Connects to | `modules/hall-ui/public/atlas.js:290` |
279
280
  | `999e1955bb1c` | certain | Context layer | `modules/hall-ui/public/atlas.html:47` |
280
281
  | `296eb6da10ca` | certain | Contribution to this goal | `modules/hall-ui/public/goals-render.js:785` |
281
- | `4fb972405d3d` | certain | Copy all {…} for Session Start | `modules/hall-ui/public/collab.js:344` |
282
+ | `4fb972405d3d` | certain | Copy all {…} for Session Start | `modules/hall-ui/public/collab.js:401` |
282
283
  | `12ee050d0180` | certain | Copy desk | `modules/hall-ui/public/copy-desk.html:15` |
283
284
  | `12ee050d0180` | certain | Copy desk | `modules/hall-ui/public/copy-desk.html:15` |
284
285
  | `12ee050d0180` | certain | Copy desk | `modules/hall-ui/public/copy-desk.html:27` |
285
286
  | `1214ea8e0d1b` | certain | Copy desk — {{worldName}} | `modules/hall-ui/public/copy-desk.html:6` |
286
287
  | `1214ea8e0d1b` | certain | Copy desk — {{worldName}} | `modules/hall-ui/public/copy-desk.html:6` |
287
- | `30764a4f0e28` | certain | Copy for Session Start | `modules/hall-ui/public/collab.js:123` |
288
+ | `30764a4f0e28` | certain | Copy for Session Start | `modules/hall-ui/public/collab.js:130` |
288
289
  | `ebc8a6c16a22` | certain | Copy parallel prompt | `modules/hall-ui/public/work.html:166` |
289
290
  | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/task.js:795` |
290
291
  | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/task.js:816` |
@@ -312,7 +313,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
312
313
  | `90691bceaf68` | certain | Could not load | `modules/hall-ui/public/task.js:982` |
313
314
  | `589a4cfc5442` | certain | Could not load idea {…}. | `modules/hall-ui/public/ideas.js:944` |
314
315
  | `192c893fc64e` | certain | Could not load modules. | `modules/hall-ui/public/modules.js:318` |
315
- | `9912c3835136` | certain | Could not load requests — reload to try again. | `modules/hall-ui/public/collab.js:615` |
316
+ | `9912c3835136` | certain | Could not load requests — reload to try again. | `modules/hall-ui/public/collab.js:744` |
316
317
  | `7775fec0fa85` | certain | Could not load sessions. | `modules/hall-ui/public/sessions.js:399` |
317
318
  | `7775fec0fa85` | certain | Could not load sessions. | `modules/hall-ui/public/sessions.js:437` |
318
319
  | `a2f2e8babef5` | certain | Could not load that page. Try again. | `modules/hall-ui/public/blockers.js:276` |
@@ -641,6 +642,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
641
642
  | `9af4b7a3a36f` | certain | Module truth | `modules/hall-ui/public/atlas.html:48` |
642
643
  | `319e9db996ea` | certain | Modules — {{worldName}} | `modules/hall-ui/public/modules.html:6` |
643
644
  | `319e9db996ea` | certain | Modules — {{worldName}} | `modules/hall-ui/public/modules.html:6` |
645
+ | `96e26b04acd8` | certain | Moot — the metrics stack was removed on the 15th, so there is nothing left to rotate. | `modules/hall-ui/public/collab.js:161` |
644
646
  | `1ae18e58fead` | certain | Most recent first. Each load of this page is itself recorded in the audit log. | `modules/hall-ui/public/sessions.js:340` |
645
647
  | `f14a91b3f625` | certain | Most recent first. Each row is one recorded work session; every id on it opens its record. | `modules/hall-ui/public/sessions.html:56` |
646
648
  | `e52ae74f0052` | certain | Move to goal | `modules/hall-ui/public/task.js:581` |
@@ -701,7 +703,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
701
703
  | `c72e0bdb834a` | certain | Not declared in module.json — this is who ships the module. | `modules/hall-ui/public/modules.js:62` |
702
704
  | `361b353ded5e` | certain | Not enough shipped work yet to chart. | `modules/hall-ui/public/hall-widgets.js:184` |
703
705
  | `90230572d017` | certain | Not found | `modules/hall-ui/public/task.js:970` |
704
- | `8226c979db4d` | certain | Not now | `modules/hall-ui/public/collab.js:519` |
706
+ | `8226c979db4d` | certain | Not now | `modules/hall-ui/public/collab.js:587` |
705
707
  | `5ffcdc1a0176` | certain | Not scored — this builder’s own profile waived every signal, or the session predates this measure. | `modules/hall-ui/public/sessions.js:100` |
706
708
  | `61250b49a90b` | certain | Not scored. | `modules/hall-ui/public/idea.js:84` |
707
709
  | `8d6afe6def47` | certain | Not signed in | `modules/hall-ui/public/settings.html:40` |
@@ -778,6 +780,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
778
780
  | `024c2f5d5f61` | certain | Pick a thought to read it. Every one of them is also a row in | `modules/hall-ui/public/sky.js:399` |
779
781
  | `45378ea261f6` | certain | Pick one… | `modules/hall-ui/public/settings.html:272` |
780
782
  | `25815a34d246` | certain | Plain speech | `modules/hall-ui/public/sessions.html:78` |
783
+ | `5b08da0632c7` | certain | Post reply | `modules/hall-ui/public/collab.js:161` |
784
+ | `5b08da0632c7` | certain | Post reply | `modules/hall-ui/public/collab.js:674` |
781
785
  | `e883f2789cae` | certain | Preferred roles | `modules/hall-ui/public/settings.html:126` |
782
786
  | `f03d68e60416` | certain | Preferred work | `modules/hall-ui/public/hall-render.js:626` |
783
787
  | `ed8edd684547` | certain | Preferred work: | `modules/hall-ui/public/hall-render.js:577` |
@@ -819,7 +823,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
819
823
  | `b03e17693dcd` | certain | Read it as a table | `modules/hall-ui/public/drachmae.js:148` |
820
824
  | `b03e17693dcd` | certain | Read it as a table | `modules/hall-ui/public/watch.js:1132` |
821
825
  | `b6fcfdd652a7` | certain | Read it here | `modules/hall-ui/public/work.html:45` |
822
- | `053df132e22c` | certain | Read the full ask | `modules/hall-ui/public/collab.js:120` |
826
+ | `053df132e22c` | certain | Read the full ask | `modules/hall-ui/public/collab.js:127` |
823
827
  | `c5f19a888a15` | certain | Read the handoff notes | `modules/hall-ui/public/task.js:481` |
824
828
  | `f9e998f4af3d` | certain | Read to the end and the button below unlocks. It is an honour system — nothing here checks your comprehension. | `modules/hall-ui/public/primer.html:100` |
825
829
  | `26e6c9879035` | certain | Reading the diagrams | `modules/hall-ui/public/diagrams.html:39` |
@@ -847,6 +851,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
847
851
  | `65e3399a8fbf` | certain | Remove filter | `modules/hall-ui/public/hall-kit.js:311` |
848
852
  | `dacd113fb3b2` | certain | Remove your image-generation key? Art generation will stop until you add one again. | `modules/hall-ui/public/settings.js:1120` |
849
853
  | `20882d6ffdd0` | certain | Removed {…} from builder {…}. | `modules/hall-ui/public/government.js:365` |
854
+ | `2063826d05f1` | certain | Replied. | `modules/hall-ui/public/collab.js:670` |
850
855
  | `9f4e519ea3e2` | certain | Repo Atlas | `modules/hall-ui/public/atlas.html:18` |
851
856
  | `9f4e519ea3e2` | certain | Repo Atlas | `modules/hall-ui/public/atlas.html:18` |
852
857
  | `7d4149cee474` | certain | Repo Atlas — a self-drawing map of the codebase | `modules/hall-ui/public/atlas.html:6` |
@@ -887,7 +892,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
887
892
  | `42cbc20a6ec8` | certain | Saves when you press Save; your next | `modules/hall-ui/public/settings.html:136` |
888
893
  | `645dd8117cf3` | certain | Say why it is being retired — the reason goes in the record. | `modules/hall-ui/public/task.js:924` |
889
894
  | `fc9d783ed0f5` | certain | Say why it is better. Whoever reviews this decides it from your reason, without asking you. | `modules/hall-ui/public/copy-desk.js:446` |
890
- | `12c1ec21a2c6` | certain | Say yes | `modules/hall-ui/public/collab.js:519` |
895
+ | `12c1ec21a2c6` | certain | Say yes | `modules/hall-ui/public/collab.js:587` |
891
896
  | `46711f7bc3df` | certain | Search every string the product shows a person, by what it says or the file it lives in. | `modules/hall-ui/public/copy-desk.html:65` |
892
897
  | `5d2ba8e72fa1` | certain | Search failed. | `modules/hall-ui/public/copy-desk.js:343` |
893
898
  | `373a7639bcb9` | certain | Sections in this primer | `modules/hall-ui/public/primer.html:52` |
@@ -923,7 +928,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
923
928
  | `ac44b08aec92` | certain | Ship it | `modules/hall-ui/public/task.js:710` |
924
929
  | `b94a6b5b3d8c` | certain | Shipped with the core | `modules/hall-ui/public/modules.html:56` |
925
930
  | `0c0a50ba1666` | certain | Shipped {…}{…}, {…}. | `modules/hall-ui/public/task.js:691` |
926
- | `6dde12eb0c78` | certain | Show all {…} | `modules/hall-ui/public/collab.js:298` |
931
+ | `6dde12eb0c78` | certain | Show all {…} | `modules/hall-ui/public/collab.js:355` |
927
932
  | `14d32a35c15f` | certain | Show my cross-project record | `modules/hall-ui/public/settings.js:514` |
928
933
  | `daa9ca82cd59` | certain | Show only | `modules/hall-ui/public/thinking.html:52` |
929
934
  | `dc0f9fe50a65` | certain | Show the setup guide again | `modules/hall-ui/public/index.html:64` |
@@ -947,7 +952,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
947
952
  | `87cee78ca134` | certain | Skip to content | `modules/hall-ui/public/shell.js:683` |
948
953
  | `688ca7b6e30f` | certain | Slop — reads as machine-written | `modules/hall-ui/public/copy-desk.html:90` |
949
954
  | `82df09a08476` | certain | So the Archon knows who you are | `modules/hall-ui/public/hall-render.js:294` |
950
- | `7da6a848cd26` | certain | Someone helped | `modules/hall-ui/public/collab.js:234` |
955
+ | `7da6a848cd26` | certain | Someone helped | `modules/hall-ui/public/collab.js:289` |
951
956
  | `e7b592185803` | certain | Someone is holding a claim on this task. It has to be released before the task can be retired. | `modules/hall-ui/public/task.js:753` |
952
957
  | `867df58c9aaa` | certain | Something else | `modules/hall-ui/public/copy-desk.html:95` |
953
958
  | `c377d8ed744b` | certain | Something went wrong. Try again. | `modules/hall-ui/public/profile-connections.js:275` |
@@ -3,17 +3,17 @@
3
3
  "generator": "scripts/gds/copy-inventory.js",
4
4
  "goal": 1000074,
5
5
  "counts": {
6
- "strings": 1933,
7
- "unique_ids": 1673,
8
- "certain": 1933,
6
+ "strings": 1938,
7
+ "unique_ids": 1677,
8
+ "certain": 1938,
9
9
  "heuristic": 0,
10
- "duplicate_ids": 178
10
+ "duplicate_ids": 179
11
11
  },
12
12
  "surfaces": {
13
13
  "builders-hall": {
14
14
  "at": "modules/hall-ui/public",
15
15
  "files": 97,
16
- "strings": 1442
16
+ "strings": 1447
17
17
  },
18
18
  "status-dashboard": {
19
19
  "at": "modules/status-ui/public",
@@ -586,7 +586,7 @@
586
586
  "text": "Asked {…}",
587
587
  "occurrences": 2,
588
588
  "at": [
589
- "modules/hall-ui/public/collab.js:84",
589
+ "modules/hall-ui/public/collab.js:91",
590
590
  "modules/hall-ui/public/watch.js:488"
591
591
  ]
592
592
  },
@@ -1170,6 +1170,16 @@
1170
1170
  "modules/hall-ui/public/people.html:6"
1171
1171
  ]
1172
1172
  },
1173
+ {
1174
+ "id": "5b08da0632c7",
1175
+ "surface": "builders-hall",
1176
+ "text": "Post reply",
1177
+ "occurrences": 2,
1178
+ "at": [
1179
+ "modules/hall-ui/public/collab.js:161",
1180
+ "modules/hall-ui/public/collab.js:674"
1181
+ ]
1182
+ },
1173
1183
  {
1174
1184
  "id": "ed8edd684547",
1175
1185
  "surface": "builders-hall",
@@ -2807,7 +2817,7 @@
2807
2817
  "surface": "builders-hall",
2808
2818
  "text": "Asked {…}",
2809
2819
  "file": "modules/hall-ui/public/collab.js",
2810
- "line": 84,
2820
+ "line": 91,
2811
2821
  "origin": "js-markup",
2812
2822
  "confidence": "certain"
2813
2823
  },
@@ -3531,6 +3541,15 @@
3531
3541
  "origin": "html-text",
3532
3542
  "confidence": "certain"
3533
3543
  },
3544
+ {
3545
+ "id": "b16bd3e36632",
3546
+ "surface": "builders-hall",
3547
+ "text": "Close this ask",
3548
+ "file": "modules/hall-ui/public/collab.js",
3549
+ "line": 263,
3550
+ "origin": "js-markup",
3551
+ "confidence": "certain"
3552
+ },
3534
3553
  {
3535
3554
  "id": "d12a2fb5730d",
3536
3555
  "surface": "builders-hall",
@@ -3671,7 +3690,7 @@
3671
3690
  "surface": "builders-hall",
3672
3691
  "text": "Copy all {…} for Session Start",
3673
3692
  "file": "modules/hall-ui/public/collab.js",
3674
- "line": 344,
3693
+ "line": 401,
3675
3694
  "origin": "js-text-assign",
3676
3695
  "confidence": "certain"
3677
3696
  },
@@ -3725,7 +3744,7 @@
3725
3744
  "surface": "builders-hall",
3726
3745
  "text": "Copy for Session Start",
3727
3746
  "file": "modules/hall-ui/public/collab.js",
3728
- "line": 123,
3747
+ "line": 130,
3729
3748
  "origin": "js-markup",
3730
3749
  "confidence": "certain"
3731
3750
  },
@@ -3977,7 +3996,7 @@
3977
3996
  "surface": "builders-hall",
3978
3997
  "text": "Could not load requests — reload to try again.",
3979
3998
  "file": "modules/hall-ui/public/collab.js",
3980
- "line": 615,
3999
+ "line": 744,
3981
4000
  "origin": "js-text-assign",
3982
4001
  "confidence": "certain"
3983
4002
  },
@@ -6933,6 +6952,15 @@
6933
6952
  "origin": "html-title",
6934
6953
  "confidence": "certain"
6935
6954
  },
6955
+ {
6956
+ "id": "96e26b04acd8",
6957
+ "surface": "builders-hall",
6958
+ "text": "Moot — the metrics stack was removed on the 15th, so there is nothing left to rotate.",
6959
+ "file": "modules/hall-ui/public/collab.js",
6960
+ "line": 161,
6961
+ "origin": "js-markup",
6962
+ "confidence": "certain"
6963
+ },
6936
6964
  {
6937
6965
  "id": "1ae18e58fead",
6938
6966
  "surface": "builders-hall",
@@ -7478,7 +7506,7 @@
7478
7506
  "surface": "builders-hall",
7479
7507
  "text": "Not now",
7480
7508
  "file": "modules/hall-ui/public/collab.js",
7481
- "line": 519,
7509
+ "line": 587,
7482
7510
  "origin": "js-markup",
7483
7511
  "confidence": "certain"
7484
7512
  },
@@ -8166,6 +8194,24 @@
8166
8194
  "origin": "html-text",
8167
8195
  "confidence": "certain"
8168
8196
  },
8197
+ {
8198
+ "id": "5b08da0632c7",
8199
+ "surface": "builders-hall",
8200
+ "text": "Post reply",
8201
+ "file": "modules/hall-ui/public/collab.js",
8202
+ "line": 161,
8203
+ "origin": "js-markup",
8204
+ "confidence": "certain"
8205
+ },
8206
+ {
8207
+ "id": "5b08da0632c7",
8208
+ "surface": "builders-hall",
8209
+ "text": "Post reply",
8210
+ "file": "modules/hall-ui/public/collab.js",
8211
+ "line": 674,
8212
+ "origin": "js-text-assign",
8213
+ "confidence": "certain"
8214
+ },
8169
8215
  {
8170
8216
  "id": "e883f2789cae",
8171
8217
  "surface": "builders-hall",
@@ -8540,7 +8586,7 @@
8540
8586
  "surface": "builders-hall",
8541
8587
  "text": "Read the full ask",
8542
8588
  "file": "modules/hall-ui/public/collab.js",
8543
- "line": 120,
8589
+ "line": 127,
8544
8590
  "origin": "js-markup",
8545
8591
  "confidence": "certain"
8546
8592
  },
@@ -8787,6 +8833,15 @@
8787
8833
  "origin": "js-notice",
8788
8834
  "confidence": "certain"
8789
8835
  },
8836
+ {
8837
+ "id": "2063826d05f1",
8838
+ "surface": "builders-hall",
8839
+ "text": "Replied.",
8840
+ "file": "modules/hall-ui/public/collab.js",
8841
+ "line": 670,
8842
+ "origin": "js-notice",
8843
+ "confidence": "certain"
8844
+ },
8790
8845
  {
8791
8846
  "id": "9f4e519ea3e2",
8792
8847
  "surface": "builders-hall",
@@ -9152,7 +9207,7 @@
9152
9207
  "surface": "builders-hall",
9153
9208
  "text": "Say yes",
9154
9209
  "file": "modules/hall-ui/public/collab.js",
9155
- "line": 519,
9210
+ "line": 587,
9156
9211
  "origin": "js-markup",
9157
9212
  "confidence": "certain"
9158
9213
  },
@@ -9476,7 +9531,7 @@
9476
9531
  "surface": "builders-hall",
9477
9532
  "text": "Show all {…}",
9478
9533
  "file": "modules/hall-ui/public/collab.js",
9479
- "line": 298,
9534
+ "line": 355,
9480
9535
  "origin": "js-text-assign",
9481
9536
  "confidence": "certain"
9482
9537
  },
@@ -9692,7 +9747,7 @@
9692
9747
  "surface": "builders-hall",
9693
9748
  "text": "Someone helped",
9694
9749
  "file": "modules/hall-ui/public/collab.js",
9695
- "line": 234,
9750
+ "line": 289,
9696
9751
  "origin": "js-markup",
9697
9752
  "confidence": "certain"
9698
9753
  },
@@ -2470,5 +2470,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
2470
2470
  landed since 1.19.996 with no explicit bump. run 35937246865. (task 1002620)
2471
2471
  1.19.998 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2472
2472
  landed since 1.19.997 with no explicit bump. run 35940192900. (task 1002620)
2473
+ 1.19.999 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2474
+ landed since 1.19.998 with no explicit bump. run 35942048393. (task 1002620)
2475
+ 1.19.1000 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2476
+ landed since 1.19.999 with no explicit bump. run 35943151697. (task 1002620)
2473
2477
  ---------------------------------------------------------------------------
2474
2478
  ```
@@ -493,6 +493,83 @@
493
493
  return lines.join('\n');
494
494
  }
495
495
 
496
+ // ---- replies (task 1004216, ADR 0330) ---------------------------------------
497
+ //
498
+ // An ask can be ANSWERED now, so the page has a second kind of row: a thing a
499
+ // person said, under the thing a person asked. These are its pure halves.
500
+
501
+ // WHEN SOMEBODY SAID IT, in the tense a reply needs. ageLabel is the wrong
502
+ // vocabulary here and not by a little — "waiting 3 days" under an answer reads
503
+ // as the answer still being owed, which is the exact opposite of what a reply
504
+ // means. A reply is a thing that HAPPENED, so it is measured backwards from
505
+ // now, not forwards from a debt.
506
+ function saidLabel(createdAt, nowMs) {
507
+ var then = createdAt ? Date.parse(createdAt) : NaN;
508
+ var now = typeof nowMs === 'number' ? nowMs : Date.now();
509
+ if (isNaN(then)) return 'just now';
510
+ var days = Math.floor((now - then) / DAY_MS);
511
+ if (days < 1) return 'today';
512
+ if (days === 1) return 'yesterday';
513
+ if (days < 14) return days + ' days ago';
514
+ return Math.floor(days / 7) + ' weeks ago';
515
+ }
516
+
517
+ // Who said it — the same fallback ladder askerOf uses, so a reply and an ask
518
+ // name the same person the same way.
519
+ function replyAuthor(reply) {
520
+ if (!reply) return '';
521
+ if (reply.builder_name) return String(reply.builder_name);
522
+ if (reply.builder_login) return String(reply.builder_login);
523
+ return reply.builder_id != null ? 'builder ' + reply.builder_id : 'someone';
524
+ }
525
+
526
+ // The thread on a row, oldest first — the order a conversation is read in, and
527
+ // deliberately the opposite of every list on this page, which sorts by what
528
+ // needs attention. A thread is not a queue.
529
+ //
530
+ // The server already sends them ordered; this sorts anyway, because the page
531
+ // must not be the thing that breaks when a cached or hand-assembled response
532
+ // arrives in another order. `created_at` ties break on id, so two replies
533
+ // written in the same second keep the order they were written in.
534
+ function threadOf(req) {
535
+ var list = (req && Array.isArray(req.replies)) ? req.replies.slice() : [];
536
+ return list.sort(function (a, b) {
537
+ var ta = Date.parse(a && a.created_at) || 0;
538
+ var tb = Date.parse(b && b.created_at) || 0;
539
+ if (ta !== tb) return ta - tb;
540
+ return Number(a && a.id) - Number(b && b.id);
541
+ });
542
+ }
543
+
544
+ // WHO MAY CLOSE AN ASK (ADR 0330). The asker always may. The ADDRESSEE may
545
+ // too — by name, or through a craft they belong to — because once the answer
546
+ // is on the row, a person who has answered in the open and cannot close it is
547
+ // a surface arguing with itself.
548
+ //
549
+ // THE SERVER IS THE AUTHORITY; this only decides whether to DRAW the control.
550
+ // The same rule runs in the UPDATE's own WHERE, so a page that got this wrong
551
+ // would offer a button that 404s, never a close it should not have had.
552
+ // Withdraw is not here at all: that stays the asker's, and `mineRow` is the
553
+ // only row that draws it.
554
+ function canClose(req, meId, myCrafts) {
555
+ if (!req || meId == null) return false;
556
+ var me = String(meId);
557
+ if (String(req.requested_by) === me) return true;
558
+ if (req.needs_builder_id != null && String(req.needs_builder_id) === me) return true;
559
+ var crafts = Array.isArray(myCrafts) ? myCrafts : [];
560
+ return !!req.needs_craft && crafts.indexOf(req.needs_craft) !== -1;
561
+ }
562
+
563
+ // A reply is capped at the same length as an ask. Stated here so the page can
564
+ // refuse before the round trip and the counter can read from one number.
565
+ var MAX_REPLY = 4000;
566
+ function validateReplyBody(text) {
567
+ var body = String(text == null ? '' : text).trim();
568
+ if (!body) return { ok: false, reason: 'empty' };
569
+ if (body.length > MAX_REPLY) return { ok: false, reason: 'too_long' };
570
+ return { ok: true, body: body };
571
+ }
572
+
496
573
  window.OTBCollabLib = {
497
574
  BANDS: BANDS, ageBand: ageBand, ageLabel: ageLabel,
498
575
  roomBaseline: roomBaseline, isRoomQuiet: isRoomQuiet, roomAgeLine: roomAgeLine,
@@ -505,5 +582,7 @@
505
582
  aOrAn: aOrAn, pairSentence: pairSentence,
506
583
  SKILL_COMMAND: SKILL_COMMAND, sessionStartPrompt: sessionStartPrompt,
507
584
  queueStartPrompt: queueStartPrompt, contextSentence: contextSentence,
585
+ saidLabel: saidLabel, replyAuthor: replyAuthor, threadOf: threadOf,
586
+ canClose: canClose, validateReplyBody: validateReplyBody, MAX_REPLY: MAX_REPLY,
508
587
  };
509
588
  })();
@@ -240,3 +240,63 @@
240
240
  /* ---- empties and the foot -------------------------------------------------- */
241
241
  .cb-empty p { font-size: 14px; }
242
242
  .cb-foot { margin: var(--sp-sm) 0 0; font-size: 12.5px; color: var(--ink-faint); max-width: var(--measure); }
243
+
244
+ /* ---- the thread (task 1004216, ADR 0330) ------------------------------------
245
+ An ask can be ANSWERED on the page now, so a row has a second kind of content
246
+ under it. It is dressed DOWN on purpose: no avatar, no bubble, no alternating
247
+ sides, no accent. The row's own face and the accent on the by-name ask are
248
+ what a glance down the list reads, and a thread that competed with them would
249
+ turn a board of asks into a chat log — which is the surface ADR 0187 §4a
250
+ declined and ADR 0330 deliberately did not build. A left rule and a shift of
251
+ the measure are the whole treatment: enough to say "this hangs off that". */
252
+ /* INDENT AND A TINT, NEVER A RULE DOWN THE EDGE. A left border is how this
253
+ sheet is specifically not allowed to mark a row (the ageing clause's own
254
+ test bans it, because a coloured edge competes with the age pill that a
255
+ glance down the column is meant to read). The opened ask already uses the
256
+ glass for "nested content", so a thread wears the same thing. */
257
+ .cb-thread {
258
+ list-style: none;
259
+ margin: 9px 0 0;
260
+ padding: 9px 12px;
261
+ background: var(--glass);
262
+ border-radius: var(--radius-sm);
263
+ }
264
+ .cb-reply + .cb-reply { margin-top: 9px; }
265
+ .cb-reply__who { font-size: 12.5px; font-weight: 600; color: var(--ink); }
266
+ .cb-reply__when { font-size: 12px; color: var(--ink-faint); margin-left: 7px; }
267
+ /* pre-wrap for the same reason the opened ask has it: an answer is written with
268
+ its own paragraphs and steps, and collapsing them would make the page's own
269
+ rendering less readable than the text a reader copies out of it. */
270
+ .cb-reply__body {
271
+ margin: 3px 0 0;
272
+ font-size: 13px;
273
+ line-height: 1.55;
274
+ color: var(--ink-soft);
275
+ white-space: pre-wrap;
276
+ max-width: var(--measure);
277
+ }
278
+
279
+ .cb-reply-bar { margin: 7px 0 0; }
280
+
281
+ /* CLOSED UNTIL ASKED FOR. A textarea open on every row would turn a page you
282
+ read into a page you are being asked to type on — and the blocks are
283
+ condensed to three rows precisely so the page stays readable. */
284
+ .cb-reply-form { margin: 9px 0 0; max-width: var(--measure); }
285
+ .cb-reply-input {
286
+ width: 100%;
287
+ font: inherit;
288
+ font-size: 13px;
289
+ line-height: 1.55;
290
+ color: var(--ink);
291
+ background: var(--glass);
292
+ border: 1px solid var(--rule);
293
+ border-radius: var(--radius-sm);
294
+ padding: 9px 11px;
295
+ resize: vertical;
296
+ }
297
+ /* NO `outline: none` HERE. The shell already draws the hall's one focus ring on
298
+ :focus-visible, and dropping it to style a field is exactly what the hall's
299
+ own audit refuses — it caught this line. The border tint is an ADDITION to
300
+ that ring, not a replacement for it. */
301
+ .cb-reply-input:focus { border-color: var(--accent-ink); }
302
+ .cb-reply-actions { display: flex; gap: 8px; margin: 7px 0 0; }