@bongos/core 1.19.907 → 1.19.908

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.bongos-core.json CHANGED
@@ -2,11 +2,11 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.907",
6
- "core_contract": "1.19.907",
7
- "source_commit": "71cb07155a010b68421b31a9154436b140d5557d",
5
+ "core_version": "1.19.908",
6
+ "core_contract": "1.19.908",
7
+ "source_commit": "9106097c832462bfa184d771528a279febabf3b5",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-20T13:52:16.387Z",
9
+ "built_at": "2026-09-20T14:28:23.616Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 502,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 2811,
20
- "tree_sha256": "b58d926d1a79850ef28b158610d628958dbbf0c143ba5327cabbcd5ad2f527d3",
20
+ "tree_sha256": "7211db73a6674b953b3bd798a44be3953f23cf655f69829ba70d840ff349c50a",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2097,12 +2097,12 @@
2097
2097
  {
2098
2098
  "path": "docs/copy-inventory.md",
2099
2099
  "mode": "0000644",
2100
- "sha256": "b018bdef70a2e46e00fa7e88d4ee489255d8d1ff9eaeecba18eb3c39ec41878d"
2100
+ "sha256": "3a121e993f87d7379836af082bebb8c857427481eb265d477b4b55584cdd604b"
2101
2101
  },
2102
2102
  {
2103
2103
  "path": "docs/copy-registry.json",
2104
2104
  "mode": "0000644",
2105
- "sha256": "88c3ac9d52e16fef3c82e09f4a8b4e8d8fa46f490e68bf370d2fd49a90bfbdee"
2105
+ "sha256": "77e94a0337636dd8e444bfca6d749c9a16a937ed8e98b372072c17f5b43cc3fe"
2106
2106
  },
2107
2107
  {
2108
2108
  "path": "docs/design/apex-pass-2-direction.md",
@@ -2632,7 +2632,7 @@
2632
2632
  {
2633
2633
  "path": "docs/module-api-changelog.md",
2634
2634
  "mode": "0000644",
2635
- "sha256": "efe7ce69b4aed84c057d34db6b6bd2bcbb8a8f7b326bab16320277f314db5a46"
2635
+ "sha256": "c871aa7368d18d6e5c8153936bd1710bf3b137df7c3a08ed276eb09aabd1b072"
2636
2636
  },
2637
2637
  {
2638
2638
  "path": "docs/modules-contract.md",
@@ -4662,22 +4662,22 @@
4662
4662
  {
4663
4663
  "path": "modules/hall-ui/public/collab-lib.js",
4664
4664
  "mode": "0000644",
4665
- "sha256": "bfadae8700cc22ea13f8bc39a3e2a1876b58da6151032e9a973402bc9bd0aaa7"
4665
+ "sha256": "baa893e9f8bd207416ee271f429964a85f7d6e1d44235c98a0a9dc20c7998049"
4666
4666
  },
4667
4667
  {
4668
4668
  "path": "modules/hall-ui/public/collab.css",
4669
4669
  "mode": "0000644",
4670
- "sha256": "884118a3b38b0c1ed5e1ac9c90c0b5994714bbabde67959f67c49e7f49536983"
4670
+ "sha256": "ee8845701481932fd9c222b5bb1714aaa552c2c0967d97fc91eef166fe6ab712"
4671
4671
  },
4672
4672
  {
4673
4673
  "path": "modules/hall-ui/public/collab.html",
4674
4674
  "mode": "0000644",
4675
- "sha256": "186a0828e1c3e44388146b94c56f239ea6b2392bd599f143c7c73029da35da32"
4675
+ "sha256": "9876929d0ce989d12dadcdfa6da5cd93ca660e0b291a24a467a920632245dd65"
4676
4676
  },
4677
4677
  {
4678
4678
  "path": "modules/hall-ui/public/collab.js",
4679
4679
  "mode": "0000644",
4680
- "sha256": "91a0751cebcbc179f28ad1cac7a6c447f90369ae40f29e5f60c1bd934ac68f85"
4680
+ "sha256": "465198338e63c762a8f099df8a43e449e804097074c62285243f4876085f6dc5"
4681
4681
  },
4682
4682
  {
4683
4683
  "path": "modules/hall-ui/public/collab.states.json",
@@ -7782,12 +7782,12 @@
7782
7782
  {
7783
7783
  "path": "package-lock.json",
7784
7784
  "mode": "0000644",
7785
- "sha256": "55fbc4950d743f2078280ad1311903120e44c8b93a84d7403fa1107321aee16c"
7785
+ "sha256": "1d02ddc9cfd0fd8ce3a40f3b2d16c322c070f7027c6dddf75efa8036968dd96c"
7786
7786
  },
7787
7787
  {
7788
7788
  "path": "package.json",
7789
7789
  "mode": "0000644",
7790
- "sha256": "6b23fd601399995c8b9b2dfc1881d2e4047b2345c61549f0a9661c4cb31ed0c5"
7790
+ "sha256": "23cd5edb1b132f21c0f9e82d8ee3d9406f0fac55df8c20b3be002a1a9b09b614"
7791
7791
  },
7792
7792
  {
7793
7793
  "path": "public-docs/index.html",
@@ -9782,7 +9782,7 @@
9782
9782
  {
9783
9783
  "path": "src/module-api.js",
9784
9784
  "mode": "0000644",
9785
- "sha256": "e7dbc1db9bf741ba4a85b171e30b9b5f05a4cf38b3b7422d8df81943c66eb7bb"
9785
+ "sha256": "95604748c175a2928c9fdc59d1214816156e084ad6e98b8295246648af37ca04"
9786
9786
  },
9787
9787
  {
9788
9788
  "path": "src/module-loader/catalog.js",
@@ -10622,7 +10622,7 @@
10622
10622
  {
10623
10623
  "path": "tests/collab_page.mjs",
10624
10624
  "mode": "0000644",
10625
- "sha256": "b710669fabe9e747fe37abf429356e80c1f7a36cd63ac308dda2a933243e2e6d"
10625
+ "sha256": "3e6ae0773f3997f82764f51373dd2e12b965d05366f7615346ba4f504151be77"
10626
10626
  },
10627
10627
  {
10628
10628
  "path": "tests/compose_demo_credentials.mjs",
@@ -11607,7 +11607,7 @@
11607
11607
  {
11608
11608
  "path": "tests/hall_collab_world.mjs",
11609
11609
  "mode": "0000644",
11610
- "sha256": "d005de58e0eabd019f616ee6c77123c5880b67034ce33dc1b01d687a2b284b10"
11610
+ "sha256": "0374c15f7bf4cfdb4cccadb51f5c62e2331413e6970a69599cb1f51899d79b0a"
11611
11611
  },
11612
11612
  {
11613
11613
  "path": "tests/hall_error_envelope.mjs",
@@ -152,7 +152,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
152
152
  | `8b736e365191` | certain | All builders | `modules/hall-ui/public/hall-render.js:1238` |
153
153
  | `b5e03617b319` | certain | All goals | `modules/hall-ui/public/goals.html:53` |
154
154
  | `e08d410571e9` | certain | All kinds | `modules/hall-ui/public/sessions.js:286` |
155
- | `9c34bccb06ef` | certain | All open asks | `modules/hall-ui/public/collab.html:71` |
155
+ | `9c34bccb06ef` | certain | All open asks | `modules/hall-ui/public/collab.html:73` |
156
156
  | `bea7817e57a4` | certain | All surfaces | `modules/hall-ui/public/copy-desk.js:301` |
157
157
  | `627c683a5e5d` | certain | All time | `modules/hall-ui/public/hall-widgets.js:130` |
158
158
  | `b38c01691857` | certain | All your work → | `modules/hall-ui/public/hall-widgets.js:110` |
@@ -163,7 +163,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
163
163
  | `69f0ca4a4d84` | certain | Analytics scope | `modules/hall-ui/public/hall-render.js:1236` |
164
164
  | `14bdceaac078` | certain | Answer the five questions and this spark becomes a Full Idea. | `modules/hall-ui/public/ideas.js:692` |
165
165
  | `0293418d5e8e` | certain | Answerable for: | `modules/hall-ui/public/profile.js:72` |
166
- | `05761b08ec8f` | certain | Answering is optional and declining costs nothing. Nobody is assigned by being asked. | `modules/hall-ui/public/collab.html:97` |
166
+ | `05761b08ec8f` | certain | Answering is optional and declining costs nothing. Nobody is assigned by being asked. | `modules/hall-ui/public/collab.html:100` |
167
167
  | `52ed0e2e3470` | certain | Any rank | `modules/hall-ui/public/task-lib.js:62` |
168
168
  | `8832c7204180` | certain | Anyone in the owning project | `modules/hall-ui/public/settings.html:291` |
169
169
  | `7d2ab55d4112` | certain | Anyone on this instance | `modules/hall-ui/public/settings.html:292` |
@@ -176,7 +176,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
176
176
  | `5fcfdf8975cf` | certain | As configuration: | `modules/hall-ui/public/government.js:829` |
177
177
  | `01a0f29ff406` | certain | As first filed | `modules/hall-ui/public/idea.js:252` |
178
178
  | `688cc6dd38ee` | certain | Asked of you | `modules/hall-ui/public/collab.html:48` |
179
- | `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/collab.js:58` |
179
+ | `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/collab.js:66` |
180
180
  | `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/watch.js:488` |
181
181
  | `8c8ec2597036` | certain | Assigned {…} to builder {…}. | `modules/hall-ui/public/government.js:463` |
182
182
  | `46714066f2da` | certain | Audit log | `modules/hall-ui/public/watch.html:141` |
@@ -275,7 +275,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
275
275
  | `12ee050d0180` | certain | Copy desk | `modules/hall-ui/public/copy-desk.html:27` |
276
276
  | `1214ea8e0d1b` | certain | Copy desk — {{worldName}} | `modules/hall-ui/public/copy-desk.html:6` |
277
277
  | `1214ea8e0d1b` | certain | Copy desk — {{worldName}} | `modules/hall-ui/public/copy-desk.html:6` |
278
- | `30764a4f0e28` | certain | Copy for Session Start | `modules/hall-ui/public/collab.js:90` |
278
+ | `30764a4f0e28` | certain | Copy for Session Start | `modules/hall-ui/public/collab.js:98` |
279
279
  | `ebc8a6c16a22` | certain | Copy parallel prompt | `modules/hall-ui/public/work.html:146` |
280
280
  | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/task.js:795` |
281
281
  | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/task.js:816` |
@@ -303,7 +303,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
303
303
  | `90691bceaf68` | certain | Could not load | `modules/hall-ui/public/task.js:982` |
304
304
  | `589a4cfc5442` | certain | Could not load idea {…}. | `modules/hall-ui/public/ideas.js:735` |
305
305
  | `192c893fc64e` | certain | Could not load modules. | `modules/hall-ui/public/modules.js:318` |
306
- | `9912c3835136` | certain | Could not load requests — reload to try again. | `modules/hall-ui/public/collab.js:529` |
306
+ | `9912c3835136` | certain | Could not load requests — reload to try again. | `modules/hall-ui/public/collab.js:551` |
307
307
  | `7775fec0fa85` | certain | Could not load sessions. | `modules/hall-ui/public/sessions.js:399` |
308
308
  | `7775fec0fa85` | certain | Could not load sessions. | `modules/hall-ui/public/sessions.js:437` |
309
309
  | `a2f2e8babef5` | certain | Could not load that page. Try again. | `modules/hall-ui/public/blockers.js:274` |
@@ -603,7 +603,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
603
603
  | `c7a670e9552d` | certain | Merged into | `modules/hall-ui/public/profile.js:489` |
604
604
  | `dce0546c9e34` | certain | Merging work does not put it in front of anyone. This is the step that does: it moves this platform — or any p | `modules/hall-ui/public/deploy.html:39` |
605
605
  | `7637613c231b` | certain | Metic rank and above may vote | `modules/hall-ui/public/builders.js:781` |
606
- | `91328a97fe68` | certain | Mingle pairs you with someone from another role. Saying no costs nothing. | `modules/hall-ui/public/collab.html:87` |
606
+ | `91328a97fe68` | certain | Mingle pairs you with someone from another role. Saying no costs nothing. | `modules/hall-ui/public/collab.html:90` |
607
607
  | `d7ce4a3bb745` | certain | Minimize the welcome panel | `modules/hall-ui/public/hall-widgets.js:52` |
608
608
  | `19b0ed5781ae` | certain | Minimum rank required to claim this task | `modules/hall-ui/public/task-lib.js:65` |
609
609
  | `64e91044df43` | certain | Mint a fresh CLI token using this browser session and paste it into your terminal — the quick way back in when | `modules/hall-ui/public/settings.html:145` |
@@ -644,7 +644,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
644
644
  | `fbb887a9b678` | certain | No goal has criteria met yet — work is in the task queue. | `modules/hall-ui/public/roadmap.js:128` |
645
645
  | `6771a8966ec3` | certain | No goals declared yet — this version is tracked by its {…} done-when criteria. | `modules/hall-ui/public/roadmap.js:106` |
646
646
  | `abc64639b134` | certain | No goals seeded yet. | `modules/hall-ui/public/roadmap.js:205` |
647
- | `139ec3636c22` | certain | No introductions right now. One appears here when a pairing round runs. | `modules/hall-ui/public/collab.html:90` |
647
+ | `139ec3636c22` | certain | No introductions right now. One appears here when a pairing round runs. | `modules/hall-ui/public/collab.html:93` |
648
648
  | `3b9823dd4579` | certain | No maintenance declared — nobody is on the hook for this module as the core advances. | `modules/hall-ui/public/modules.js:92` |
649
649
  | `64a4281934d1` | certain | No match. Try a page name, or an id like | `modules/hall-ui/public/palette.js:182` |
650
650
  | `4f89817b92e5` | certain | No onboarding steps recorded yet. | `modules/hall-ui/public/hall-render.js:941` |
@@ -662,13 +662,13 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
662
662
  | `c9800f8b6bc8` | certain | No versions declared yet. | `modules/hall-ui/public/roadmap.js:427` |
663
663
  | `4654849396a3` | certain | No work reviewed yet. | `modules/hall-ui/public/hall-widgets.js:150` |
664
664
  | `086665af6208` | certain | No {…} sessions recorded. Choose another kind to widen the ledger. | `modules/hall-ui/public/sessions.js:145` |
665
- | `1967d2176f2e` | certain | Nobody has an open ask right now. | `modules/hall-ui/public/collab.html:75` |
666
- | `c65c9f5c02e3` | certain | Nobody is waiting on you. Requests reach you by role — | `modules/hall-ui/public/collab.html:53` |
665
+ | `1967d2176f2e` | certain | Nobody has an open ask right now. | `modules/hall-ui/public/collab.html:78` |
666
+ | `c65c9f5c02e3` | certain | Nobody is waiting on you. Requests reach you by role — | `modules/hall-ui/public/collab.html:54` |
667
667
  | `91c409a4aea5` | certain | Nobody vouched for this name — anyone can file a request naming anyone. Confirm who is asking before you admit | `modules/hall-ui/public/watch.js:374` |
668
668
  | `c72e0bdb834a` | certain | Not declared in module.json — this is who ships the module. | `modules/hall-ui/public/modules.js:62` |
669
669
  | `361b353ded5e` | certain | Not enough shipped work yet to chart. | `modules/hall-ui/public/hall-widgets.js:184` |
670
670
  | `90230572d017` | certain | Not found | `modules/hall-ui/public/task.js:970` |
671
- | `8226c979db4d` | certain | Not now | `modules/hall-ui/public/collab.js:435` |
671
+ | `8226c979db4d` | certain | Not now | `modules/hall-ui/public/collab.js:457` |
672
672
  | `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` |
673
673
  | `61250b49a90b` | certain | Not scored. | `modules/hall-ui/public/idea.js:84` |
674
674
  | `8d6afe6def47` | certain | Not signed in | `modules/hall-ui/public/settings.html:40` |
@@ -780,7 +780,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
780
780
  | `b03e17693dcd` | certain | Read it as a table | `modules/hall-ui/public/drachmae.js:148` |
781
781
  | `b03e17693dcd` | certain | Read it as a table | `modules/hall-ui/public/watch.js:1132` |
782
782
  | `b6fcfdd652a7` | certain | Read it here | `modules/hall-ui/public/work.html:45` |
783
- | `053df132e22c` | certain | Read the full ask | `modules/hall-ui/public/collab.js:90` |
783
+ | `053df132e22c` | certain | Read the full ask | `modules/hall-ui/public/collab.js:98` |
784
784
  | `c5f19a888a15` | certain | Read the handoff notes | `modules/hall-ui/public/task.js:481` |
785
785
  | `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` |
786
786
  | `26e6c9879035` | certain | Reading the diagrams | `modules/hall-ui/public/diagrams.html:39` |
@@ -847,7 +847,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
847
847
  | `42cbc20a6ec8` | certain | Saves when you press Save; your next | `modules/hall-ui/public/settings.html:136` |
848
848
  | `645dd8117cf3` | certain | Say why it is being retired — the reason goes in the record. | `modules/hall-ui/public/task.js:924` |
849
849
  | `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` |
850
- | `12c1ec21a2c6` | certain | Say yes | `modules/hall-ui/public/collab.js:435` |
850
+ | `12c1ec21a2c6` | certain | Say yes | `modules/hall-ui/public/collab.js:457` |
851
851
  | `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` |
852
852
  | `5d2ba8e72fa1` | certain | Search failed. | `modules/hall-ui/public/copy-desk.js:343` |
853
853
  | `373a7639bcb9` | certain | Sections in this primer | `modules/hall-ui/public/primer.html:52` |
@@ -882,7 +882,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
882
882
  | `ac44b08aec92` | certain | Ship it | `modules/hall-ui/public/task.js:710` |
883
883
  | `b94a6b5b3d8c` | certain | Shipped with the core | `modules/hall-ui/public/modules.html:56` |
884
884
  | `0c0a50ba1666` | certain | Shipped {…}{…}, {…}. | `modules/hall-ui/public/task.js:691` |
885
- | `6dde12eb0c78` | certain | Show all {…} | `modules/hall-ui/public/collab.js:253` |
885
+ | `6dde12eb0c78` | certain | Show all {…} | `modules/hall-ui/public/collab.js:275` |
886
886
  | `14d32a35c15f` | certain | Show my cross-project record | `modules/hall-ui/public/settings.js:514` |
887
887
  | `dc0f9fe50a65` | certain | Show the setup guide again | `modules/hall-ui/public/index.html:64` |
888
888
  | `2af4c0f2b4b9` | certain | Showing {…} of {…}. | `modules/hall-ui/public/ideas.js:638` |
@@ -905,7 +905,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
905
905
  | `87cee78ca134` | certain | Skip to content | `modules/hall-ui/public/shell.js:663` |
906
906
  | `688ca7b6e30f` | certain | Slop — reads as machine-written | `modules/hall-ui/public/copy-desk.html:90` |
907
907
  | `82df09a08476` | certain | So the Archon knows who you are | `modules/hall-ui/public/hall-render.js:294` |
908
- | `7da6a848cd26` | certain | Someone helped | `modules/hall-ui/public/collab.js:203` |
908
+ | `7da6a848cd26` | certain | Someone helped | `modules/hall-ui/public/collab.js:211` |
909
909
  | `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` |
910
910
  | `867df58c9aaa` | certain | Something else | `modules/hall-ui/public/copy-desk.html:95` |
911
911
  | `c377d8ed744b` | certain | Something went wrong. Try again. | `modules/hall-ui/public/profile-connections.js:275` |
@@ -1132,14 +1132,14 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1132
1132
  | `23c68db6db4e` | certain | You created this task, but it has already moved past planning. Retiring it now is a change to the record, so i | `modules/hall-ui/public/task.js:776` |
1133
1133
  | `cf0c107a39fc` | certain | You created this task, but it has shipped. Shipped work is immutable history — nobody can retire it, whatever | `modules/hall-ui/public/task.js:769` |
1134
1134
  | `b91183c02c63` | certain | You created this task, but someone is holding a claim on it. Once that is released you can retire it yourself. | `modules/hall-ui/public/task.js:774` |
1135
- | `da274462bb30` | certain | You have no open asks. | `modules/hall-ui/public/collab.html:64` |
1135
+ | `da274462bb30` | certain | You have no open asks. | `modules/hall-ui/public/collab.html:66` |
1136
1136
  | `6b759151f722` | certain | You have reached the end. The button below is now active. | `modules/hall-ui/public/primer.js:309` |
1137
1137
  | `6d5a4ca58dd6` | certain | You haven’t joined any goals yet. | `modules/hall-ui/public/goals.js:83` |
1138
1138
  | `8e527ab12334` | certain | You {…}. One vote per member. | `modules/hall-ui/public/board-room.js:348` |
1139
1139
  | `8e1915b19274` | certain | You're in the {…} server with your rank role. | `modules/hall-ui/public/settings.js:833` |
1140
1140
  | `d8c542541c15` | certain | You're not signed in yet. Sign in to manage your connections, your keys, your dev box and the way the hall beh | `modules/hall-ui/public/settings.html:41` |
1141
1141
  | `3a6ed99ec333` | certain | You've been approved before — sign in and pick up where you left off. | `modules/hall-ui/public/hall-render.js:367` |
1142
- | `7d26333b5fb0` | certain | Your asks | `modules/hall-ui/public/collab.html:61` |
1142
+ | `7d26333b5fb0` | certain | Your asks | `modules/hall-ui/public/collab.html:62` |
1143
1143
  | `f96bc227dba0` | certain | Your choice | `modules/hall-ui/public/settings.html:359` |
1144
1144
  | `f20a4adfd5a8` | certain | Your dev box builds itself in a minute or two and the app chimes when it's ready. It lives in the menu bar on | `modules/hall-ui/public/hall-render.js:825` |
1145
1145
  | `909b0b7c6ffa` | certain | Your display name | `modules/hall-ui/public/settings.html:84` |
@@ -1284,7 +1284,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1284
1284
  | `594962dc9ec3` | certain | s into the view containers below (falling back to | `modules/hall-ui/public/index.html:52` |
1285
1285
  | `2a42549b34ae` | certain | said, when flagged: | `modules/hall-ui/public/copy-desk.js:124` |
1286
1286
  | `9bec9eb4829e` | certain | scope: {…} | `modules/hall-ui/public/goals-render.js:836` |
1287
- | `a13ee0cde7f2` | certain | set yours in Settings | `modules/hall-ui/public/collab.html:54` |
1287
+ | `a13ee0cde7f2` | certain | set yours in Settings | `modules/hall-ui/public/collab.html:55` |
1288
1288
  | `a6f55d7aa6f7` | certain | shipped (live) | `modules/hall-ui/public/roadmap.js:298` |
1289
1289
  | `026ba1289d4d` | certain | shipped · | `modules/hall-ui/public/goals-render.js:758` |
1290
1290
  | `ec6d8c900bc8` | certain | sign in | `modules/hall-ui/public/profile-charts.js:502` |
@@ -541,7 +541,7 @@
541
541
  "text": "Asked {…}",
542
542
  "occurrences": 2,
543
543
  "at": [
544
- "modules/hall-ui/public/collab.js:58",
544
+ "modules/hall-ui/public/collab.js:66",
545
545
  "modules/hall-ui/public/watch.js:488"
546
546
  ]
547
547
  },
@@ -2412,7 +2412,7 @@
2412
2412
  "surface": "builders-hall",
2413
2413
  "text": "All open asks",
2414
2414
  "file": "modules/hall-ui/public/collab.html",
2415
- "line": 71,
2415
+ "line": 73,
2416
2416
  "origin": "html-text",
2417
2417
  "confidence": "certain"
2418
2418
  },
@@ -2511,7 +2511,7 @@
2511
2511
  "surface": "builders-hall",
2512
2512
  "text": "Answering is optional and declining costs nothing. Nobody is assigned by being asked.",
2513
2513
  "file": "modules/hall-ui/public/collab.html",
2514
- "line": 97,
2514
+ "line": 100,
2515
2515
  "origin": "html-text",
2516
2516
  "confidence": "certain"
2517
2517
  },
@@ -2628,7 +2628,7 @@
2628
2628
  "surface": "builders-hall",
2629
2629
  "text": "Asked {…}",
2630
2630
  "file": "modules/hall-ui/public/collab.js",
2631
- "line": 58,
2631
+ "line": 66,
2632
2632
  "origin": "js-markup",
2633
2633
  "confidence": "certain"
2634
2634
  },
@@ -3519,7 +3519,7 @@
3519
3519
  "surface": "builders-hall",
3520
3520
  "text": "Copy for Session Start",
3521
3521
  "file": "modules/hall-ui/public/collab.js",
3522
- "line": 90,
3522
+ "line": 98,
3523
3523
  "origin": "js-markup",
3524
3524
  "confidence": "certain"
3525
3525
  },
@@ -3771,7 +3771,7 @@
3771
3771
  "surface": "builders-hall",
3772
3772
  "text": "Could not load requests — reload to try again.",
3773
3773
  "file": "modules/hall-ui/public/collab.js",
3774
- "line": 529,
3774
+ "line": 551,
3775
3775
  "origin": "js-text-assign",
3776
3776
  "confidence": "certain"
3777
3777
  },
@@ -6471,7 +6471,7 @@
6471
6471
  "surface": "builders-hall",
6472
6472
  "text": "Mingle pairs you with someone from another role. Saying no costs nothing.",
6473
6473
  "file": "modules/hall-ui/public/collab.html",
6474
- "line": 87,
6474
+ "line": 90,
6475
6475
  "origin": "html-text",
6476
6476
  "confidence": "certain"
6477
6477
  },
@@ -6840,7 +6840,7 @@
6840
6840
  "surface": "builders-hall",
6841
6841
  "text": "No introductions right now. One appears here when a pairing round runs.",
6842
6842
  "file": "modules/hall-ui/public/collab.html",
6843
- "line": 90,
6843
+ "line": 93,
6844
6844
  "origin": "html-text",
6845
6845
  "confidence": "certain"
6846
6846
  },
@@ -7002,7 +7002,7 @@
7002
7002
  "surface": "builders-hall",
7003
7003
  "text": "Nobody has an open ask right now.",
7004
7004
  "file": "modules/hall-ui/public/collab.html",
7005
- "line": 75,
7005
+ "line": 78,
7006
7006
  "origin": "html-text",
7007
7007
  "confidence": "certain"
7008
7008
  },
@@ -7011,7 +7011,7 @@
7011
7011
  "surface": "builders-hall",
7012
7012
  "text": "Nobody is waiting on you. Requests reach you by role —",
7013
7013
  "file": "modules/hall-ui/public/collab.html",
7014
- "line": 53,
7014
+ "line": 54,
7015
7015
  "origin": "html-text",
7016
7016
  "confidence": "certain"
7017
7017
  },
@@ -7056,7 +7056,7 @@
7056
7056
  "surface": "builders-hall",
7057
7057
  "text": "Not now",
7058
7058
  "file": "modules/hall-ui/public/collab.js",
7059
- "line": 435,
7059
+ "line": 457,
7060
7060
  "origin": "js-markup",
7061
7061
  "confidence": "certain"
7062
7062
  },
@@ -8064,7 +8064,7 @@
8064
8064
  "surface": "builders-hall",
8065
8065
  "text": "Read the full ask",
8066
8066
  "file": "modules/hall-ui/public/collab.js",
8067
- "line": 90,
8067
+ "line": 98,
8068
8068
  "origin": "js-markup",
8069
8069
  "confidence": "certain"
8070
8070
  },
@@ -8667,7 +8667,7 @@
8667
8667
  "surface": "builders-hall",
8668
8668
  "text": "Say yes",
8669
8669
  "file": "modules/hall-ui/public/collab.js",
8670
- "line": 435,
8670
+ "line": 457,
8671
8671
  "origin": "js-markup",
8672
8672
  "confidence": "certain"
8673
8673
  },
@@ -8982,7 +8982,7 @@
8982
8982
  "surface": "builders-hall",
8983
8983
  "text": "Show all {…}",
8984
8984
  "file": "modules/hall-ui/public/collab.js",
8985
- "line": 253,
8985
+ "line": 275,
8986
8986
  "origin": "js-text-assign",
8987
8987
  "confidence": "certain"
8988
8988
  },
@@ -9189,7 +9189,7 @@
9189
9189
  "surface": "builders-hall",
9190
9190
  "text": "Someone helped",
9191
9191
  "file": "modules/hall-ui/public/collab.js",
9192
- "line": 203,
9192
+ "line": 211,
9193
9193
  "origin": "js-markup",
9194
9194
  "confidence": "certain"
9195
9195
  },
@@ -11232,7 +11232,7 @@
11232
11232
  "surface": "builders-hall",
11233
11233
  "text": "You have no open asks.",
11234
11234
  "file": "modules/hall-ui/public/collab.html",
11235
- "line": 64,
11235
+ "line": 66,
11236
11236
  "origin": "html-text",
11237
11237
  "confidence": "certain"
11238
11238
  },
@@ -11295,7 +11295,7 @@
11295
11295
  "surface": "builders-hall",
11296
11296
  "text": "Your asks",
11297
11297
  "file": "modules/hall-ui/public/collab.html",
11298
- "line": 61,
11298
+ "line": 62,
11299
11299
  "origin": "html-text",
11300
11300
  "confidence": "certain"
11301
11301
  },
@@ -12600,7 +12600,7 @@
12600
12600
  "surface": "builders-hall",
12601
12601
  "text": "set yours in Settings",
12602
12602
  "file": "modules/hall-ui/public/collab.html",
12603
- "line": 54,
12603
+ "line": 55,
12604
12604
  "origin": "html-text",
12605
12605
  "confidence": "certain"
12606
12606
  },
@@ -2288,5 +2288,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
2288
2288
  landed since 1.19.905 with no explicit bump. run 35514202453. (task 1002620)
2289
2289
  1.19.907 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2290
2290
  landed since 1.19.906 with no explicit bump. run 35514739370. (task 1002620)
2291
+ 1.19.908 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2292
+ landed since 1.19.907 with no explicit bump. run 35516559010. (task 1002620)
2291
2293
  ---------------------------------------------------------------------------
2292
2294
  ```
@@ -73,6 +73,75 @@
73
73
  return 'waiting ' + weeks + ' weeks';
74
74
  }
75
75
 
76
+ // A PILL MARKS A ROW WORSE THAN ITS ROOM (task 1004067, from idea 1001065).
77
+ //
78
+ // Task 1004041 fixed half of this: the words now carry the real age, and the
79
+ // two calm bands lost their ring. What it could not fix from inside a single
80
+ // row is the case the report is actually about — a room where EVERY row is
81
+ // genuinely past a week. There the condition is not too loose; it is correct
82
+ // on all fourteen, and fourteen correct alarms are still not a signal. The
83
+ // instrument is wrong, not the threshold: a per-row badge can only say "this
84
+ // row is bad", and it has no way to say "this row is bad AND so is every other
85
+ // one", which is the fact a reader needs.
86
+ //
87
+ // So the room states its own condition once, in the block head, and a row
88
+ // wears the pill only when it is MORE SEVERE than that baseline. On a mixed
89
+ // board no band is dominant, nothing is muted, and the page reads exactly as
90
+ // it does today. On a uniformly stale board the alarm is said once instead of
91
+ // fourteen times, and the per-row words still carry each real age — so nothing
92
+ // goes silently dead, which is the criterion the bands exist to satisfy.
93
+ //
94
+ // Two dials, both deliberately blunt. A room under BASELINE_MIN_ROWS is not a
95
+ // wall — four pills can be read one at a time, so a short list keeps every
96
+ // one. BASELINE_SHARE is below 1 because thirteen-of-fourteen reads as a wall
97
+ // just as much as fourteen does, and a rule that only fires on unanimity is a
98
+ // rule that almost never fires.
99
+ var BASELINE_MIN_ROWS = 4;
100
+ var BASELINE_SHARE = 0.7;
101
+
102
+ // Only a band that actually WEARS a pill can be a baseline (severity >= 2 —
103
+ // aging and stale; collab.css rings those two and leaves the calm pair as
104
+ // plain text). A room that is uniformly 'just asked' has no alarm to move to
105
+ // the head, and announcing one there would invent the very noise this removes.
106
+ function roomBaseline(reqs, nowMs) {
107
+ var list = Array.isArray(reqs) ? reqs : [];
108
+ if (list.length < BASELINE_MIN_ROWS) return null;
109
+ var counts = {};
110
+ for (var i = 0; i < list.length; i += 1) {
111
+ var id = ageBand(list[i] && list[i].created_at, nowMs).id;
112
+ counts[id] = (counts[id] || 0) + 1;
113
+ }
114
+ // BANDS is severest-first, and two bands cannot both clear a share above a
115
+ // half, so the first match is the only match.
116
+ for (var j = 0; j < BANDS.length; j += 1) {
117
+ var band = BANDS[j];
118
+ var n = counts[band.id] || 0;
119
+ if (band.severity >= 2 && n / list.length >= BASELINE_SHARE) {
120
+ return { band: band, count: n, total: list.length };
121
+ }
122
+ }
123
+ return null;
124
+ }
125
+
126
+ // At or below the room's baseline, a row is the rule and reads quiet; above
127
+ // it, a row is the exception and keeps its pill. With no baseline nothing is
128
+ // quieted, which is what makes this inert on every mixed board.
129
+ function isRoomQuiet(band, baseline) {
130
+ if (!band || !baseline) return false;
131
+ return band.severity <= baseline.band.severity;
132
+ }
133
+
134
+ // The fact the pills used to repeat, said once. The band's own label supplies
135
+ // the words, so the head and the rows can never describe the same threshold
136
+ // two different ways.
137
+ function roomAgeLine(baseline) {
138
+ if (!baseline) return '';
139
+ var many = baseline.count === baseline.total
140
+ ? 'all ' + baseline.total
141
+ : baseline.count + ' of ' + baseline.total;
142
+ return many + ' ' + baseline.band.label;
143
+ }
144
+
76
145
  // Oldest first WITHIN the page, because the thing most at risk of dying
77
146
  // silently should be read first. This is in ADDITION to the band, never
78
147
  // instead of it.
@@ -336,6 +405,8 @@
336
405
 
337
406
  window.OTBCollabLib = {
338
407
  BANDS: BANDS, ageBand: ageBand, ageLabel: ageLabel,
408
+ roomBaseline: roomBaseline, isRoomQuiet: isRoomQuiet, roomAgeLine: roomAgeLine,
409
+ BASELINE_MIN_ROWS: BASELINE_MIN_ROWS, BASELINE_SHARE: BASELINE_SHARE,
339
410
  byAgeOldestFirst: byAgeOldestFirst, byNewestFirst: byNewestFirst,
340
411
  askerOf: askerOf, contextOf: contextOf,
341
412
  directionLine: directionLine, boardLine: boardLine,
@@ -43,6 +43,33 @@
43
43
  padding-right: 0;
44
44
  }
45
45
 
46
+ /* THE ROOM'S OWN CONDITION IS NOT A PER-ROW WARNING (task 1004067). When a
47
+ block is uniformly old, every row's band is correct and every row's pill is
48
+ therefore identical — the wall the report describes. A row at or below its
49
+ room's baseline drops to the same plain quiet text the calm bands wear, so
50
+ the only chips left in the column are the rows that are worse than their
51
+ room. Two classes, so this outranks the band ink it replaces without an
52
+ !important. The WORDS are untouched: each row still states its own real age,
53
+ which is what keeps an old ask visibly aging rather than silently dead. */
54
+ .cb-age.cb-age--quiet {
55
+ color: var(--ink-soft);
56
+ border-color: transparent;
57
+ padding-left: 0;
58
+ padding-right: 0;
59
+ font-weight: 400;
60
+ }
61
+
62
+ /* The fact the chips used to repeat, stated once in the head. It sits in the
63
+ band's own ink because here it IS the exception — one line on a page, not one
64
+ per row — and it is the only thing on the head that is allowed to be loud. */
65
+ .cb-block__age {
66
+ font-size: 13px;
67
+ letter-spacing: 0;
68
+ color: var(--ink-soft);
69
+ }
70
+ .cb-block__age--aging { color: var(--warn); }
71
+ .cb-block__age--stale { color: var(--danger); font-weight: 600; }
72
+
46
73
  /* ---- the figure strip -----------------------------------------------------
47
74
  The shell's .stat-row, unchanged, except that this page's third tile holds
48
75
  WORDS (the roles you answer for) rather than a figure. The shell's own
@@ -46,6 +46,7 @@
46
46
  <section class="scroll cb-block" aria-labelledby="cb-for-me-h">
47
47
  <div class="cb-block__head">
48
48
  <h2 class="scroll__h" id="cb-for-me-h">Asked of you <span class="cb-block__n" id="cb-for-me-n"></span></h2>
49
+ <span class="cb-block__age" id="cb-for-me-age" hidden></span>
49
50
  <span class="cb-faces" id="cb-for-me-faces" aria-hidden="true"></span>
50
51
  </div>
51
52
  <ul class="ov-rows" id="cb-for-me"></ul>
@@ -59,6 +60,7 @@
59
60
  <section class="scroll cb-block" aria-labelledby="cb-mine-h">
60
61
  <div class="cb-block__head">
61
62
  <h2 class="scroll__h" id="cb-mine-h">Your asks <span class="cb-block__n" id="cb-mine-n"></span></h2>
63
+ <span class="cb-block__age" id="cb-mine-age" hidden></span>
62
64
  </div>
63
65
  <ul class="ov-rows" id="cb-mine"></ul>
64
66
  <div class="empty-state cb-empty" id="cb-mine-empty" hidden><p>You have no open asks.</p></div>
@@ -69,6 +71,7 @@
69
71
  <section class="scroll cb-block cb-block--all" aria-labelledby="cb-all-h">
70
72
  <div class="cb-block__head">
71
73
  <h2 class="scroll__h" id="cb-all-h">All open asks <span class="cb-block__n" id="cb-all-n"></span></h2>
74
+ <span class="cb-block__age" id="cb-all-age" hidden></span>
72
75
  <span class="cb-faces" id="cb-all-faces" aria-hidden="true"></span>
73
76
  </div>
74
77
  <ul class="ov-rows" id="cb-all"></ul>
@@ -53,9 +53,17 @@
53
53
  // exact timestamp stays on the title, where a reader who wants the date can
54
54
  // still reach it — which is also why the separate date line that used to sit
55
55
  // under this pill is gone: the same fact twice is one fact too many.
56
- function ageChip(req, nowMs) {
56
+ //
57
+ // `baseline` is the block's own room condition (L.roomBaseline), and it is the
58
+ // second half of the same verdict: where the label stops fourteen old rows
59
+ // reading as fourteen copies of one alarm, the baseline stops them WEARING
60
+ // fourteen copies of one alarm. A row at or below its room's baseline is the
61
+ // rule, not the exception, so it drops the ring and the danger ink and keeps
62
+ // only its words — the head says the room's condition once instead.
63
+ function ageChip(req, nowMs, baseline) {
57
64
  const band = L.ageBand(req.created_at, nowMs);
58
- return `<span class="fact-pill cb-age cb-age--${band.id}" title="Asked ${escapeHtml(String(req.created_at || ''))}">${escapeHtml(L.ageLabel(req.created_at, nowMs))}</span>`;
65
+ const quiet = L.isRoomQuiet(band, baseline) ? ' cb-age--quiet' : '';
66
+ return `<span class="fact-pill cb-age cb-age--${band.id}${quiet}" title="Asked ${escapeHtml(String(req.created_at || ''))}">${escapeHtml(L.ageLabel(req.created_at, nowMs))}</span>`;
59
67
  }
60
68
 
61
69
  // A DOM id per row that is stable, unique and safe to put in an attribute. The
@@ -175,14 +183,14 @@
175
183
  // chat mirror). What the page owes a helper is the request, its age, its
176
184
  // context, and who to answer — and their face. A by-name ask is the personal
177
185
  // call on this reader, so its row is the LIT one (.cb-row--live).
178
- function forMeRow(req, nowMs, extra, key) {
186
+ function forMeRow(req, nowMs, extra, key, baseline) {
179
187
  const live = req.needs_builder_id != null ? ' cb-row--live' : '';
180
188
  return `<li class="ov-row ov-row--lead cb-row${live}" data-id="${escapeHtml(String(req.id))}"${extra ? ' data-extra hidden' : ''}>
181
189
  ${faceHtml(L.faceOf(req, 'in'))}
182
190
  <div class="ov-row__main">${askHtml(req, key)}
183
191
  <div class="ov-row__facts">${directionFact(req, 'in')}${contextChip(req)}</div>
184
192
  </div>
185
- <div class="ov-row__right">${ageChip(req, nowMs)}</div>
193
+ <div class="ov-row__right">${ageChip(req, nowMs, baseline)}</div>
186
194
  </li>`;
187
195
  }
188
196
 
@@ -198,12 +206,12 @@
198
206
  // which is precisely the distinction a reader could no longer make. Moving the
199
207
  // pill down to the facts line puts the warning with the other facts about the
200
208
  // ask and leaves the right column as what it is here: the place you act.
201
- function mineRow(req, nowMs, extra, key) {
209
+ function mineRow(req, nowMs, extra, key, baseline) {
202
210
  const id = escapeHtml(String(req.id));
203
211
  return `<li class="ov-row ov-row--lead cb-row" data-id="${id}"${extra ? ' data-extra hidden' : ''}>
204
212
  ${faceHtml(L.faceOf(req, 'out'))}
205
213
  <div class="ov-row__main">${askHtml(req, key)}
206
- <div class="ov-row__facts">${directionFact(req, 'out')}${contextChip(req)}${ageChip(req, nowMs)}</div>
214
+ <div class="ov-row__facts">${directionFact(req, 'out')}${contextChip(req)}${ageChip(req, nowMs, baseline)}</div>
207
215
  </div>
208
216
  <div class="ov-row__right">
209
217
  <div class="ov-row__actions">
@@ -216,13 +224,13 @@
216
224
 
217
225
  // A row on the board of everyone's asks: the asker's face, the third-person
218
226
  // line, no actions — settling is the asker's, in their own block.
219
- function allRow(req, nowMs, extra, key) {
227
+ function allRow(req, nowMs, extra, key, baseline) {
220
228
  return `<li class="ov-row ov-row--lead cb-row" data-id="${escapeHtml(String(req.id))}"${extra ? ' data-extra hidden' : ''}>
221
229
  ${faceHtml(L.faceOf(req, 'in'))}
222
230
  <div class="ov-row__main">${askHtml(req, key)}
223
231
  <div class="ov-row__facts">${boardFact(req)}${contextChip(req)}</div>
224
232
  </div>
225
- <div class="ov-row__right">${ageChip(req, nowMs)}</div>
233
+ <div class="ov-row__right">${ageChip(req, nowMs, baseline)}</div>
226
234
  </li>`;
227
235
  }
228
236
 
@@ -235,13 +243,27 @@
235
243
  function paintBlock(key, rows, rowFn, nowMs, faces) {
236
244
  const list = rows.slice().sort(L.byNewestFirst);
237
245
  const { shown, hidden } = L.splitShown(list, SHOWN);
246
+ // Over the WHOLE list, not the shown three: the door hides rows, it does not
247
+ // change what the room is, and a baseline that flipped when someone pressed
248
+ // "Show all" would re-alarm the rows it had just quieted.
249
+ const baseline = L.roomBaseline(list, nowMs);
238
250
  const host = $(`#cb-${key}`);
239
251
  if (host) {
240
- host.innerHTML = shown.map((r) => rowFn(r, nowMs, false, key)).join('')
241
- + hidden.map((r) => rowFn(r, nowMs, true, key)).join('');
252
+ host.innerHTML = shown.map((r) => rowFn(r, nowMs, false, key, baseline)).join('')
253
+ + hidden.map((r) => rowFn(r, nowMs, true, key, baseline)).join('');
242
254
  }
243
255
  const n = $(`#cb-${key}-n`);
244
256
  if (n) n.textContent = list.length ? String(list.length) : '';
257
+ // The room's condition, said once, beside the count that scopes it.
258
+ const age = $(`#cb-${key}-age`);
259
+ if (age) {
260
+ const line = L.roomAgeLine(baseline);
261
+ age.textContent = line;
262
+ age.hidden = !line;
263
+ age.className = line
264
+ ? `cb-block__age cb-block__age--${baseline.band.id}`
265
+ : 'cb-block__age';
266
+ }
245
267
  const empty = $(`#cb-${key}-empty`);
246
268
  if (empty) empty.hidden = list.length > 0;
247
269
  const facesEl = $(`#cb-${key}-faces`);
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.907",
3
+ "version": "1.19.908",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.907",
9
+ "version": "1.19.908",
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.19.907",
3
+ "version": "1.19.908",
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",
package/src/module-api.js CHANGED
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
71
71
  // there. scripts/gds/bump-version.js still rewrites the literal below; it appends
72
72
  // the entry to that file. Look for a version's history there, not here.
73
73
  // ---------------------------------------------------------------------------
74
- const CORE_VERSION = '1.19.907'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.908'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
75
75
 
76
76
  // A namespaced logger so a module's log lines are attributable + consistent.
77
77
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -136,6 +136,98 @@ test('the two calm bands are not chips, and the date is not said twice', () => {
136
136
  assert.match(js, /title="Asked \$\{escapeHtml\(String\(req\.created_at/, 'the exact date is still reachable');
137
137
  });
138
138
 
139
+ // ---- THE ROOM'S OWN CONDITION (task 1004067, from idea 1001065) -----------
140
+ //
141
+ // The report: fourteen of fourteen rows wore the "waiting over a week" pill, so
142
+ // the loudest thing on the page carried no information. Task 1004041 made the
143
+ // WORDS differ, which is why these tests are about the TREATMENT — fourteen
144
+ // differently-worded rows in identical danger ink and identical rings still read
145
+ // as a wall. Each case below is run through the lib, not grepped, so a rule that
146
+ // is wrong fails here rather than looking plausible in a diff.
147
+ const room = (...ages) => ages.map((d) => ({ created_at: daysAgo(d) }));
148
+
149
+ test('a uniformly old room states its condition once instead of on every row', () => {
150
+ const L = lib();
151
+ // The reported board, reproduced: fourteen rows, every one past a week.
152
+ const rows = room(8, 9, 11, 13, 15, 16, 18, 21, 24, 27, 30, 34, 38, 41);
153
+ const baseline = L.roomBaseline(rows, NOW);
154
+ assert.ok(baseline, 'fourteen of fourteen is a room condition, not fourteen warnings');
155
+ assert.equal(baseline.band.id, 'stale');
156
+ assert.equal(L.roomAgeLine(baseline), 'all 14 waiting over a week');
157
+ const loud = rows.filter((r) => !L.isRoomQuiet(L.ageBand(r.created_at, NOW), baseline));
158
+ assert.equal(loud.length, 0, 'no row is worse than a room where every row is the same');
159
+ // And nothing is silently dead: each row still says its own real age.
160
+ const words = new Set(rows.map((r) => L.ageLabel(r.created_at, NOW)));
161
+ assert.ok(words.size > 1, 'the per-row words still carry the differing ages');
162
+ });
163
+
164
+ test('the pill is kept for the row that is worse than its room', () => {
165
+ const L = lib();
166
+ // Six of eight sitting a few days, two genuinely old. The two are the whole
167
+ // point of the column, and before this they were indistinguishable from the six.
168
+ const rows = room(4, 4, 5, 5, 5, 6, 21, 30);
169
+ const baseline = L.roomBaseline(rows, NOW);
170
+ assert.equal(baseline.band.id, 'aging');
171
+ assert.equal(L.roomAgeLine(baseline), '6 of 8 waiting a few days');
172
+ const loud = rows
173
+ .filter((r) => !L.isRoomQuiet(L.ageBand(r.created_at, NOW), baseline))
174
+ .map((r) => L.ageLabel(r.created_at, NOW));
175
+ assert.deepEqual(loud, ['waiting 3 weeks', 'waiting 4 weeks'], 'only the exceptions keep a chip');
176
+ });
177
+
178
+ test('a mixed room is left exactly as it was', () => {
179
+ const L = lib();
180
+ // No band is dominant here, so nothing is quieted and nothing is announced —
181
+ // which is what keeps this inert on the board as it usually looks.
182
+ const rows = room(0.2, 0.5, 1, 2, 4, 5, 9, 21);
183
+ assert.equal(L.roomBaseline(rows, NOW), null);
184
+ assert.equal(L.roomAgeLine(null), '');
185
+ for (const r of rows) {
186
+ assert.equal(L.isRoomQuiet(L.ageBand(r.created_at, NOW), null), false, 'no baseline quiets nothing');
187
+ }
188
+ });
189
+
190
+ test('a short list keeps every pill, and a calm room announces nothing', () => {
191
+ const L = lib();
192
+ // Three chips can be read one at a time; a wall needs a crowd.
193
+ assert.equal(L.roomBaseline(room(30, 30, 30), NOW), null, 'under the minimum, every row keeps its own');
194
+ assert.equal(L.BASELINE_MIN_ROWS, 4);
195
+ // A room that is uniformly calm has no alarm to move to the head. Announcing
196
+ // one there would invent the noise this removes.
197
+ assert.equal(L.roomBaseline(room(0.1, 0.2, 0.3, 0.4, 0.5), NOW), null, 'all fresh says nothing');
198
+ assert.equal(L.roomBaseline(room(1, 1, 2, 2, 2), NOW), null, 'all waiting-a-day says nothing either');
199
+ });
200
+
201
+ test('the room line and the rows cannot describe the threshold two ways', () => {
202
+ const L = lib();
203
+ // The head's words come from the band's own label, so there is one vocabulary.
204
+ for (const b of L.BANDS) {
205
+ const line = L.roomAgeLine({ band: b, count: 9, total: 12 });
206
+ assert.equal(line, `9 of 12 ${b.label}`, `${b.id} reads in its own words`);
207
+ }
208
+ });
209
+
210
+ test('the quiet treatment is wired through the render, not just defined', () => {
211
+ const js = read('modules', 'hall-ui', 'public', 'collab.js');
212
+ assert.match(js, /function ageChip\(req, nowMs, baseline\)/, 'the chip is told about its room');
213
+ assert.match(js, /L\.isRoomQuiet\(band, baseline\)/, 'through the lib, so the rule is the tested one');
214
+ assert.match(js, /cb-age--quiet/, 'and the class reaches the markup');
215
+ // Over the WHOLE list: a baseline computed on the shown three would flip when
216
+ // a reader pressed "Show all" and re-alarm the rows it had just quieted.
217
+ assert.match(js, /const baseline = L\.roomBaseline\(list, nowMs\)/, 'the room is the whole block');
218
+ const html = read('modules', 'hall-ui', 'public', 'collab.html');
219
+ for (const key of ['for-me', 'mine', 'all']) {
220
+ assert.ok(html.includes(`id="cb-${key}-age"`), `the ${key} head has somewhere to say it`);
221
+ }
222
+ const css = read('modules', 'hall-ui', 'public', 'collab.css');
223
+ assert.match(
224
+ css,
225
+ /\.cb-age\.cb-age--quiet\s*\{[^}]*border-color: transparent/,
226
+ 'the quieted row drops its ring',
227
+ );
228
+ assert.match(css, /\.cb-age\.cb-age--quiet\s*\{[^}]*color: var\(--ink-soft\)/, 'and the danger ink with it');
229
+ });
230
+
139
231
  test('the alarm does not sit beside the accent control', () => {
140
232
  // DESIGN.md spends the accent only on what is pressable or live. On "Your
141
233
  // asks" the age pill (danger ink) used to share the right column with the
@@ -230,7 +230,11 @@ test('the door and the copy control are on the row, and the copy control is reac
230
230
  // One request can appear in three blocks at once, so the id is block-scoped.
231
231
  assert.match(js, /function askId\(key, id\)/);
232
232
  assert.match(js, /cb-ask-\$\{key\}-/);
233
- assert.match(js, /rowFn\(r, nowMs, false, key\)/, 'and paintBlock hands the key down');
233
+ // A bracket class, not a closing paren: paintBlock also hands the row its
234
+ // block's age baseline (task 1004067), and pinning the exact arity would red
235
+ // this on an argument the invariant — that the KEY reaches the row — does not
236
+ // care about.
237
+ assert.match(js, /rowFn\(r, nowMs, false, key[,)]/, 'and paintBlock hands the key down');
234
238
 
235
239
  const css = read('collab.css');
236
240
  for (const cls of ['.cb-ask ', '.cb-ask__door', '.cb-ask__copy', '.cb-ask__full']) {
@@ -262,8 +266,12 @@ test('the age is a state pill in the row\'s right column, and every band has its
262
266
  assert.match(css, /\.cb-age--stale\s*\{[^}]*var\(--danger\)/, 'stale is the danger ink');
263
267
  assert.match(css, /\.cb-age--aging\s*\{[^}]*var\(--warn\)/, 'aging is the warn ink');
264
268
  const js = read('collab.js');
265
- assert.match(js, /class="fact-pill cb-age cb-age--\$\{band\.id\}"/, 'the pill is the shell\'s fact-pill');
266
- assert.match(js, /<div class="ov-row__right">\$\{ageChip\(req, nowMs\)\}/, 'in the right column, so a glance down the list reads the ages');
269
+ // Both pins stop short of the closing character, because the band's class is
270
+ // now followed by the room's quiet modifier and ageChip by the baseline that
271
+ // decides it (task 1004067). What they assert is unchanged: the shell's pill,
272
+ // in the right column.
273
+ assert.match(js, /class="fact-pill cb-age cb-age--\$\{band\.id\}/, 'the pill is the shell\'s fact-pill');
274
+ assert.match(js, /<div class="ov-row__right">\$\{ageChip\(req, nowMs[,)]/, 'in the right column, so a glance down the list reads the ages');
267
275
  });
268
276
 
269
277
  // ---- the copy desk: quieter, and no fact lost ----------------------------------