@bongos/core 1.19.272 → 1.19.273

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,22 +2,22 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.272",
6
- "core_contract": "1.19.272",
7
- "source_commit": "1ddcabf5f0c390df6bf2db273da05131d7c5555d",
5
+ "core_version": "1.19.273",
6
+ "core_contract": "1.19.273",
7
+ "source_commit": "5537eeef23f8f0daa60fcb4a167c9a95ec085a17",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-21T01:58:30.188Z",
9
+ "built_at": "2026-08-21T02:47:17.902Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 318,
13
13
  "agent_docs_stubbed": 22,
14
- "functional_verbatim": 1369,
14
+ "functional_verbatim": 1370,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1709,
20
- "tree_sha256": "7e96896dddb704ffea439416bad0d7ba6ad81ead9d79ed34212de45a2df50f71",
19
+ "file_count": 1710,
20
+ "tree_sha256": "6446c48d86f464c04e57b8332758031a3427ca7756c6dc01ec7933c989635dde",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -1427,12 +1427,12 @@
1427
1427
  {
1428
1428
  "path": "docs/copy-inventory.md",
1429
1429
  "mode": "0000644",
1430
- "sha256": "5766467665c33bcc5a3bdec568af6a02c75f5e88d82a3e8fe2459eccb19c15da"
1430
+ "sha256": "47ba743c5ce981d8afafa22013cf596f0ccd26e3f25a43c656188ccd105fafdb"
1431
1431
  },
1432
1432
  {
1433
1433
  "path": "docs/copy-registry.json",
1434
1434
  "mode": "0000644",
1435
- "sha256": "ded30cde6d371dc2172ae778cf079edc00bbfee208002673a6e60e9b5a8ac95b"
1435
+ "sha256": "473494d43714c9d300487ce7fe976997c3c8d8c3b2d1daeea6481d18cb1997ec"
1436
1436
  },
1437
1437
  {
1438
1438
  "path": "docs/design-contract.md",
@@ -3347,7 +3347,7 @@
3347
3347
  {
3348
3348
  "path": "modules/hall-ui/public/dom-utils.js",
3349
3349
  "mode": "0000644",
3350
- "sha256": "2f9521e8e5c6d9f8cc52769affb229fa72e2c2db6f1063e34aaf587a54ebb86b"
3350
+ "sha256": "ab48833410d7dc97bd2f0cd332d2ede95a632c87af50338bce660034e71d881a"
3351
3351
  },
3352
3352
  {
3353
3353
  "path": "modules/hall-ui/public/drachmae.html",
@@ -3632,7 +3632,7 @@
3632
3632
  {
3633
3633
  "path": "modules/hall-ui/public/task.js",
3634
3634
  "mode": "0000644",
3635
- "sha256": "ac6bfa459924a43005625e9c2655a5a1397c941dfa0727594bb25f930180d36a"
3635
+ "sha256": "25e487bb73e1c36397350fe89953a07c0a7742670e89589ad1c4cea07c830d74"
3636
3636
  },
3637
3637
  {
3638
3638
  "path": "modules/hall-ui/public/watch.css",
@@ -3662,7 +3662,7 @@
3662
3662
  {
3663
3663
  "path": "modules/hall-ui/public/work.js",
3664
3664
  "mode": "0000644",
3665
- "sha256": "3c9fc42cfe2954fc285153c93c9e686870097535d4efa83af5bbdfc3f5527a98"
3665
+ "sha256": "296b44d30dfc32579518290316ee934f5abe652ecd481a057feee221de6eae9b"
3666
3666
  },
3667
3667
  {
3668
3668
  "path": "modules/ideas/CLAUDE.md",
@@ -4472,12 +4472,12 @@
4472
4472
  {
4473
4473
  "path": "package-lock.json",
4474
4474
  "mode": "0000644",
4475
- "sha256": "b77fc259ddf810fa62ea5e745751449a5dc49847311ddf4199a997df9dcd06ed"
4475
+ "sha256": "18002184d4180e23e816413d0ea52da34989862b7ad7021b1df84790efed6602"
4476
4476
  },
4477
4477
  {
4478
4478
  "path": "package.json",
4479
4479
  "mode": "0000644",
4480
- "sha256": "725dd9f78abd547ef32e6d9a9b886ecf447fa1bd62a747df49943e2a1e047949"
4480
+ "sha256": "db5a0de515b3ba49f58b4fa629136f0ff9327bfaa45c5ac8fd994751f2390c07"
4481
4481
  },
4482
4482
  {
4483
4483
  "path": "public-docs/index.html",
@@ -6122,7 +6122,7 @@
6122
6122
  {
6123
6123
  "path": "src/module-api.js",
6124
6124
  "mode": "0000644",
6125
- "sha256": "67c1067ae657f640493d8bfa3f7001ce64f416d0176afd6e84be387349a9578e"
6125
+ "sha256": "c8c489bd626bd990b5d2230f8f535350abb2cf754910fd3bc7869e56fb1444ce"
6126
6126
  },
6127
6127
  {
6128
6128
  "path": "src/module-loader/catalog.js",
@@ -7309,6 +7309,11 @@
7309
7309
  "mode": "0000644",
7310
7310
  "sha256": "a048f93e0962bf30869c797e53be26954af276522adba4644a5b233d870e5286"
7311
7311
  },
7312
+ {
7313
+ "path": "tests/hall_error_envelope.mjs",
7314
+ "mode": "0000644",
7315
+ "sha256": "1d9c1d345a6fe25eacf810703a3e7f9f3b33f8e982aef49364e19eb4469de668"
7316
+ },
7312
7317
  {
7313
7318
  "path": "tests/hall_nav.mjs",
7314
7319
  "mode": "0000644",
@@ -40,14 +40,14 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
40
40
  | `4195d0d114e4` | 6x | Archons only. | modules/hall-ui/public/gate.html:26, modules/hall-ui/public/government.html:26, modules/hall-ui/public/harbor.html:26 |
41
41
  | `eeda19200aeb` | 6x | Cloud Bongos | public-landing/projects.html:419, public-landing/projects.html:457, public-landing/projects.html:686 |
42
42
  | `512ab32e3bf2` | 4x | Close box | modules/hall-ui/public/box-panel.js:149, modules/hall-ui/public/box-panel.js:163, modules/hall-ui/public/box-panel.js:206 |
43
- | `b31fc908c962` | 4x | You claimed #{…}. Open a terminal to start work. | modules/hall-ui/public/goals-page.js:674, modules/hall-ui/public/goals-page.js:926, modules/hall-ui/public/work.js:747 |
43
+ | `b31fc908c962` | 4x | You claimed #{…}. Open a terminal to start work. | modules/hall-ui/public/goals-page.js:674, modules/hall-ui/public/goals-page.js:926, modules/hall-ui/public/work.js:751 |
44
44
  | `5df2baabf82e` | 4x | ← Back | public-landing/projects.html:747, public-landing/projects.html:816, public-landing/projects.html:856 |
45
45
  | `a78477a24a48` | 3x | Builders' Hall | modules/hall-ui/public/index.html:12, modules/hall-ui/public/index.html:12, modules/hall-ui/public/index.html:38 |
46
- | `a873e7c29d80` | 3x | Copy prompt | modules/hall-ui/public/task.js:252, modules/hall-ui/public/task.js:269, modules/hall-ui/public/work.js:446 |
46
+ | `a873e7c29d80` | 3x | Copy prompt | modules/hall-ui/public/task.js:258, modules/hall-ui/public/task.js:275, modules/hall-ui/public/work.js:446 |
47
47
  | `df335a1224ae` | 3x | Member since {…} | modules/hall-ui/public/builders.js:757, modules/hall-ui/public/builders.js:811, modules/hall-ui/public/profile.js:58 |
48
48
  | `c661548d5140` | 3x | Next → | public-landing/projects.html:748, public-landing/projects.html:817, public-landing/projects.html:857 |
49
49
  | `f6f68ba322be` | 3x | Open {…} | modules/hall-ui/public/goal-inbox.js:53, modules/hall-ui/public/goal-inbox.js:69, modules/hall-ui/public/goals.js:67 |
50
- | `aa4db91b5732` | 3x | Released #{…}. It returns to the queue. | modules/hall-ui/public/goals-page.js:949, modules/hall-ui/public/work.js:783, modules/hall-ui/public/work.js:836 |
50
+ | `aa4db91b5732` | 3x | Released #{…}. It returns to the queue. | modules/hall-ui/public/goals-page.js:949, modules/hall-ui/public/work.js:792, modules/hall-ui/public/work.js:845 |
51
51
  | `e57ec24e13ef` | 3x | Sign in with GitHub | modules/hall-ui/public/builders.js:553, modules/hall-ui/public/builders.js:660, modules/hall-ui/public/shell.js:265 |
52
52
  | `df38941b25a6` | 3x | Sign in with GitHub | public-landing/projects.html:525, public-landing/projects.html:583, public-landing/projects.html:692 |
53
53
  | `b2b399fdd6a4` | 3x | in progress | modules/hall-ui/public/goals-page.js:403, modules/hall-ui/public/roadmap.js:108, modules/hall-ui/public/roadmap.js:194 |
@@ -67,7 +67,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
67
67
  | `563d29ed86d8` | 2x | Bulk actions | modules/hall-ui/public/goals.html:140, modules/hall-ui/public/work.html:118 |
68
68
  | `46b33550d52b` | 2x | Bulk claim | modules/hall-ui/public/goals.html:143, modules/hall-ui/public/work.html:121 |
69
69
  | `c10806b50c61` | 2x | Claim task {…} | modules/hall-ui/public/goals-page.js:581, modules/hall-ui/public/work.js:356 |
70
- | `a832f32b5597` | 2x | Claimed {…} tasks. Open a terminal to start work. | modules/hall-ui/public/goals-page.js:677, modules/hall-ui/public/work.js:750 |
70
+ | `a832f32b5597` | 2x | Claimed {…} tasks. Open a terminal to start work. | modules/hall-ui/public/goals-page.js:677, modules/hall-ui/public/work.js:754 |
71
71
  | `cfe0f4c4fcc2` | 2x | Closing your box… (a few seconds) | modules/hall-ui/public/box-panel.js:265, modules/hall-ui/public/box-panel.js:370 |
72
72
  | `9b16a22bf24c` | 2x | Connect Discord & join the server | modules/hall-ui/public/builders.js:1215, modules/hall-ui/public/settings.js:826 |
73
73
  | `12ee050d0180` | 2x | Copy desk | modules/hall-ui/public/copy-desk.html:15, modules/hall-ui/public/copy-desk.html:15 |
@@ -108,7 +108,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
108
108
  | `27d9721f358f` | certain | + Invite | `modules/hall-ui/public/goals-page.js:1436` |
109
109
  | `646fab1157fe` | certain | + {…} more project{…} not publicly listed. | `modules/hall-ui/public/profile.js:230` |
110
110
  | `9a663ca57b14` | certain | , claiming, and shipping show — render as rich in-feed widgets or as plain text. Widgets are prettier but spen | `modules/hall-ui/public/settings.html:230` |
111
- | `ac57fe1ccd6e` | certain | , follow its acceptance criteria, stay within touches[], /builder-ship | `modules/hall-ui/public/work.js:735` |
111
+ | `ac57fe1ccd6e` | certain | , follow its acceptance criteria, stay within touches[], /builder-ship | `modules/hall-ui/public/work.js:739` |
112
112
  | `d36226548dc9` | certain | , membership | `modules/hall-ui/public/government.js:786` |
113
113
  | `741e355954ac` | certain | , not at ship). | `modules/hall-ui/public/diagrams.html:61` |
114
114
  | `b31a6bd7edc5` | certain | , or | `modules/hall-ui/public/profile.js:265` |
@@ -165,7 +165,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
165
165
  | `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/watch.js:205` |
166
166
  | `8c8ec2597036` | certain | Assigned {…} to builder {…}. | `modules/hall-ui/public/government.js:401` |
167
167
  | `46714066f2da` | certain | Audit log | `modules/hall-ui/public/watch.html:127` |
168
- | `7fef0ae0ef9a` | certain | Awaiting the grader / a confirmation before it can ship. | `modules/hall-ui/public/task.js:247` |
168
+ | `7fef0ae0ef9a` | certain | Awaiting the grader / a confirmation before it can ship. | `modules/hall-ui/public/task.js:253` |
169
169
  | `ecfbb10d4ca9` | certain | Awaiting the owner/manager's approval | `modules/hall-ui/public/goals-page.js:1318` |
170
170
  | `08afb1257b71` | certain | Back to home | `modules/hall-ui/public/primer.html:68` |
171
171
  | `08afb1257b71` | certain | Back to home | `modules/hall-ui/public/primer.js:516` |
@@ -196,8 +196,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
196
196
  | `cab7a9526ca1` | certain | Changes save the moment you pick. “Default” clears your override and falls back to the system's choice. | `modules/hall-ui/public/settings.html:259` |
197
197
  | `4b714191b423` | certain | Changes touching protected build surfaces, held for your approval. | `modules/hall-ui/public/gate.js:226` |
198
198
  | `e6982a9ff948` | certain | Charter library | `modules/hall-ui/public/government.js:610` |
199
- | `f8725cf3ba62` | certain | Checking dependency order… | `modules/hall-ui/public/work.js:696` |
200
- | `7a41b18c0de8` | certain | Checking for conflicts… | `modules/hall-ui/public/work.js:675` |
199
+ | `f8725cf3ba62` | certain | Checking dependency order… | `modules/hall-ui/public/work.js:700` |
200
+ | `7a41b18c0de8` | certain | Checking for conflicts… | `modules/hall-ui/public/work.js:679` |
201
201
  | `aa3ba7d28a76` | certain | Checking your key… | `modules/hall-ui/public/settings.js:1013` |
202
202
  | `1c6b0e3ffc0e` | certain | Choose a setup | `modules/hall-ui/public/builders.js:984` |
203
203
  | `6c88cdf417f1` | certain | Choose which sound plays for each build event — one when Claude waits for your input, another when a task ship | `modules/hall-ui/public/settings.html:283` |
@@ -206,7 +206,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
206
206
  | `c10806b50c61` | certain | Claim task {…} | `modules/hall-ui/public/work.js:356` |
207
207
  | `84664050c372` | certain | Claimed by another builder | `modules/hall-ui/public/goals-page.js:587` |
208
208
  | `a832f32b5597` | certain | Claimed {…} tasks. Open a terminal to start work. | `modules/hall-ui/public/goals-page.js:677` |
209
- | `a832f32b5597` | certain | Claimed {…} tasks. Open a terminal to start work. | `modules/hall-ui/public/work.js:750` |
209
+ | `a832f32b5597` | certain | Claimed {…} tasks. Open a terminal to start work. | `modules/hall-ui/public/work.js:754` |
210
210
  | `18a03475e536` | certain | Claude Code | `modules/hall-ui/public/builders.js:1051` |
211
211
  | `b9c64fe023a9` | certain | Claude Desktop app | `modules/hall-ui/public/builders.js:984` |
212
212
  | `9edebf179aa3` | certain | Claude Online | `modules/hall-ui/public/builders.js:984` |
@@ -229,7 +229,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
229
229
  | `cfe0f4c4fcc2` | certain | Closing your box… (a few seconds) | `modules/hall-ui/public/box-panel.js:370` |
230
230
  | `92ca0a0e5924` | certain | Code → Environment → “{…} Dev Box” | `modules/hall-ui/public/builders.js:984` |
231
231
  | `530d83153e17` | certain | Codebase detail | `modules/hall-ui/public/atlas.html:41` |
232
- | `2867c85d196d` | certain | Confirm that verification for #{…} actually passed? | `modules/hall-ui/public/task.js:284` |
232
+ | `2867c85d196d` | certain | Confirm that verification for #{…} actually passed? | `modules/hall-ui/public/task.js:290` |
233
233
  | `9b16a22bf24c` | certain | Connect Discord & join the server | `modules/hall-ui/public/builders.js:1215` |
234
234
  | `9b16a22bf24c` | certain | Connect Discord & join the server | `modules/hall-ui/public/settings.js:826` |
235
235
  | `9f8d8e07224f` | certain | Connect your Claude Desktop to your dev box with a one-time pairing code — the guided flow lives on its own pa | `modules/hall-ui/public/settings.html:196` |
@@ -244,8 +244,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
244
244
  | `1214ea8e0d1b` | certain | Copy desk — {{worldName}} | `modules/hall-ui/public/copy-desk.html:6` |
245
245
  | `7cabea700b57` | certain | Copy not supported here — select the value and copy by hand. | `modules/hall-ui/public/box-panel.js:415` |
246
246
  | `ebc8a6c16a22` | certain | Copy parallel prompt | `modules/hall-ui/public/work.html:123` |
247
- | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/task.js:252` |
248
- | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/task.js:269` |
247
+ | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/task.js:258` |
248
+ | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/task.js:275` |
249
249
  | `a873e7c29d80` | certain | Copy prompt | `modules/hall-ui/public/work.js:446` |
250
250
  | `8e2046777710` | certain | Copy prompt for task {…} | `modules/hall-ui/public/goals-page.js:582` |
251
251
  | `8e2046777710` | certain | Copy prompt for task {…} | `modules/hall-ui/public/work.js:356` |
@@ -267,7 +267,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
267
267
  | `04824d351824` | certain | Could not copy — select the text and copy it manually. | `modules/hall-ui/public/copy-on-click.js:110` |
268
268
  | `fa309d1d0104` | certain | Could not create rank: {…} | `modules/hall-ui/public/government.js:386` |
269
269
  | `01f0308c66e0` | certain | Could not invite that builder just now. | `modules/hall-ui/public/goals-page.js:1490` |
270
- | `0adbf0652899` | certain | Could not load #{…} | `modules/hall-ui/public/task.js:303` |
270
+ | `0adbf0652899` | certain | Could not load #{…} | `modules/hall-ui/public/task.js:309` |
271
271
  | `dec4b11f316d` | certain | Could not load dev boxes just now. | `modules/hall-ui/public/harbor.js:288` |
272
272
  | `0f7c244312b1` | certain | Could not load government data just now. | `modules/hall-ui/public/government.js:883` |
273
273
  | `cd00bf198661` | certain | Could not load held pull requests just now. | `modules/hall-ui/public/gate.js:180` |
@@ -400,7 +400,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
400
400
  | `a28b1a567f1a` | certain | GitHub username | `modules/hall-ui/public/builders.js:553` |
401
401
  | `51bd60197133` | certain | Go back | `modules/hall-ui/public/drachmae.js:162` |
402
402
  | `51bd60197133` | certain | Go back | `modules/hall-ui/public/primer.js:620` |
403
- | `13acaeb4b0bf` | certain | Goal #{…} | `modules/hall-ui/public/task.js:196` |
403
+ | `13acaeb4b0bf` | certain | Goal #{…} | `modules/hall-ui/public/task.js:202` |
404
404
  | `9e70797b7e97` | certain | Goal id | `modules/hall-ui/public/goals-page.js:1243` |
405
405
  | `529460e82058` | certain | Goal invitations to you | `modules/hall-ui/public/goal-inbox.js:113` |
406
406
  | `e2a9e33abe60` | certain | Goal tasks | `modules/hall-ui/public/goals.html:104` |
@@ -464,7 +464,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
464
464
  | `35a15eb0a117` | certain | Last 30 days | `modules/hall-ui/public/hall-widgets.js:129` |
465
465
  | `9be8b839eff8` | certain | Last 7 days | `modules/hall-ui/public/hall-widgets.js:129` |
466
466
  | `59f0bc78a28f` | certain | Last 90 days | `modules/hall-ui/public/hall-widgets.js:130` |
467
- | `13bae4dfb28e` | certain | Last claimed by | `modules/hall-ui/public/task.js:207` |
467
+ | `13bae4dfb28e` | certain | Last claimed by | `modules/hall-ui/public/task.js:213` |
468
468
  | `1526a7ae8c85` | certain | Latest version: v{…}. | `modules/hall-ui/public/settings.js:1356` |
469
469
  | `7c9b7a89353b` | certain | Leave goal | `modules/hall-ui/public/goals-page.js:1315` |
470
470
  | `f192ff6563f9` | certain | Leave your GitHub username and an Archon will let you in. No coding needed to start — once you're approved, si | `modules/hall-ui/public/builders.js:553` |
@@ -557,7 +557,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
557
557
  | `3fd79013ae4a` | certain | None on disk. | `modules/hall-ui/public/modules.html:49` |
558
558
  | `c72e0bdb834a` | certain | Not declared in module.json — this is who ships the module. | `modules/hall-ui/public/modules.js:49` |
559
559
  | `361b353ded5e` | certain | Not enough shipped work yet to chart. | `modules/hall-ui/public/hall-widgets.js:184` |
560
- | `90230572d017` | certain | Not found | `modules/hall-ui/public/task.js:298` |
560
+ | `90230572d017` | certain | Not found | `modules/hall-ui/public/task.js:304` |
561
561
  | `8d6afe6def47` | certain | Not signed in | `modules/hall-ui/public/settings.html:33` |
562
562
  | `19adac0efed1` | certain | Not yet available | `modules/hall-ui/public/not-ready.html:24` |
563
563
  | `2c19f41704b9` | certain | Not yet available — {{worldName}} | `modules/hall-ui/public/not-ready.html:6` |
@@ -565,10 +565,10 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
565
565
  | `571b9b22dbda` | certain | Not yet ready — blocked by dependencies or awaiting promotion. These become claimable when their blockers ship | `modules/hall-ui/public/work.html:87` |
566
566
  | `0c59d118db9b` | certain | Note (optional) | `modules/hall-ui/public/task-detail.js:372` |
567
567
  | `95f8f8a4b288` | certain | Nothing flagged here. That is either good news or an unread queue — the duplicates below are the cheapest plac | `modules/hall-ui/public/copy-desk.js:172` |
568
- | `fec5d78497e8` | certain | Nothing in the backlog right now. | `modules/hall-ui/public/work.js:944` |
568
+ | `fec5d78497e8` | certain | Nothing in the backlog right now. | `modules/hall-ui/public/work.js:953` |
569
569
  | `18ce0723be0d` | certain | Nothing is waiting — no held changes need your approval. | `modules/hall-ui/public/gate.js:188` |
570
570
  | `ad9a17a8a5eb` | certain | Nothing shipped yet. | `modules/hall-ui/public/profile.js:144` |
571
- | `ad9a17a8a5eb` | certain | Nothing shipped yet. | `modules/hall-ui/public/work.js:905` |
571
+ | `ad9a17a8a5eb` | certain | Nothing shipped yet. | `modules/hall-ui/public/work.js:914` |
572
572
  | `42909e1460c4` | certain | Nothing to submit — every module here already ships with the core. | `modules/hall-ui/public/modules.js:166` |
573
573
  | `9d25ba1d2f17` | certain | Off voice — says it in the wrong register | `modules/hall-ui/public/copy-desk.html:91` |
574
574
  | `55bc72820efc` | certain | Older → | `modules/hall-ui/public/sessions.html:58` |
@@ -583,12 +583,12 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
583
583
  | `3366b115217b` | certain | Open navigation | `modules/hall-ui/public/shell.js:295` |
584
584
  | `0f0b1e62148d` | certain | Open online environment | `modules/hall-ui/public/box-panel.js:421` |
585
585
  | `855277dff074` | certain | Open task #{…} | `modules/hall-ui/public/goals-page.js:702` |
586
- | `855277dff074` | certain | Open task #{…} | `modules/hall-ui/public/work.js:954` |
586
+ | `855277dff074` | certain | Open task #{…} | `modules/hall-ui/public/work.js:963` |
587
587
  | `e0810149de64` | certain | Open task details | `modules/hall-ui/public/goals-page.js:589` |
588
588
  | `e0810149de64` | certain | Open task details | `modules/hall-ui/public/work.js:341` |
589
589
  | `99c630009152` | certain | Open tasks whose declared files overlap — sequence these before two builders collide. | `modules/hall-ui/public/goals.html:90` |
590
590
  | `99c630009152` | certain | Open tasks whose declared files overlap — sequence these before two builders collide. | `modules/hall-ui/public/goals.html:155` |
591
- | `29ff278e96a8` | certain | Open the Work Board | `modules/hall-ui/public/task.js:252` |
591
+ | `29ff278e96a8` | certain | Open the Work Board | `modules/hall-ui/public/task.js:258` |
592
592
  | `e706a4836ce8` | certain | Open the pairing page | `modules/hall-ui/public/settings.html:201` |
593
593
  | `2cad724171e6` | certain | Open your online environment. | `modules/hall-ui/public/builders.js:984` |
594
594
  | `f6f68ba322be` | certain | Open {…} | `modules/hall-ui/public/goal-inbox.js:53` |
@@ -645,7 +645,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
645
645
  | `9ea556e7b78b` | certain | Reason (optional) | `modules/hall-ui/public/task-detail.js:423` |
646
646
  | `7df3fd4ebf41` | certain | Reason (shown to the builder) | `modules/hall-ui/public/harbor.js:146` |
647
647
  | `06cbba1440b1` | certain | Rebase owed — new claims paused | `modules/hall-ui/public/builders.js:752` |
648
- | `58fb6fe4b47e` | certain | Recent history could not be loaded right now. | `modules/hall-ui/public/work.js:1043` |
648
+ | `58fb6fe4b47e` | certain | Recent history could not be loaded right now. | `modules/hall-ui/public/work.js:1052` |
649
649
  | `3c41dbf7c212` | certain | Recent ledger | `modules/hall-ui/public/watch.js:578` |
650
650
  | `fbce2d89706b` | certain | Recent works | `modules/hall-ui/public/profile.html:61` |
651
651
  | `0b2d1327608f` | certain | Recently shipped | `modules/hall-ui/public/hall-widgets.js:107` |
@@ -654,11 +654,11 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
654
654
  | `dba9d3f3af13` | certain | Recorded sessions | `modules/hall-ui/public/sessions.html:41` |
655
655
  | `58af483d7a84` | certain | Release task {…} | `modules/hall-ui/public/goals-page.js:584` |
656
656
  | `6f86e17007c6` | certain | Release your claim on #{…}? It returns to the queue and no {…} are earned. | `modules/hall-ui/public/goals-page.js:944` |
657
- | `6f86e17007c6` | certain | Release your claim on #{…}? It returns to the queue and no {…} are earned. | `modules/hall-ui/public/work.js:828` |
658
- | `975ffb256651` | certain | Release {…}? {…} to the queue and no {…} are earned. | `modules/hall-ui/public/work.js:777` |
657
+ | `6f86e17007c6` | certain | Release your claim on #{…}? It returns to the queue and no {…} are earned. | `modules/hall-ui/public/work.js:837` |
658
+ | `975ffb256651` | certain | Release {…}? {…} to the queue and no {…} are earned. | `modules/hall-ui/public/work.js:786` |
659
659
  | `aa4db91b5732` | certain | Released #{…}. It returns to the queue. | `modules/hall-ui/public/goals-page.js:949` |
660
- | `aa4db91b5732` | certain | Released #{…}. It returns to the queue. | `modules/hall-ui/public/work.js:783` |
661
- | `aa4db91b5732` | certain | Released #{…}. It returns to the queue. | `modules/hall-ui/public/work.js:836` |
660
+ | `aa4db91b5732` | certain | Released #{…}. It returns to the queue. | `modules/hall-ui/public/work.js:792` |
661
+ | `aa4db91b5732` | certain | Released #{…}. It returns to the queue. | `modules/hall-ui/public/work.js:845` |
662
662
  | `9c74a2572f4d` | certain | Remote control (recommended) | `modules/hall-ui/public/builders.js:984` |
663
663
  | `65e3399a8fbf` | certain | Remove filter | `modules/hall-ui/public/hall-kit.js:249` |
664
664
  | `dacd113fb3b2` | certain | Remove your image-generation key? Art generation will stop until you add one again. | `modules/hall-ui/public/settings.js:1080` |
@@ -710,8 +710,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
710
710
  | `bed8f9758ac0` | certain | See how ranks work → | `modules/hall-ui/public/not-ready.html:32` |
711
711
  | `17d5b5739f46` | certain | See the work board → | `modules/hall-ui/public/builders.js:1205` |
712
712
  | `e6afd2262c6e` | certain | See what's blocking | `modules/hall-ui/public/goals-page.js:350` |
713
- | `75dc5463facc` | certain | Select at least 2 waiting tasks to copy a parallel-session prompt. | `modules/hall-ui/public/work.js:660` |
714
- | `a98882faa482` | certain | Select at least 2 waiting tasks to copy a sequential prompt. | `modules/hall-ui/public/work.js:685` |
713
+ | `75dc5463facc` | certain | Select at least 2 waiting tasks to copy a parallel-session prompt. | `modules/hall-ui/public/work.js:664` |
714
+ | `a98882faa482` | certain | Select at least 2 waiting tasks to copy a sequential prompt. | `modules/hall-ui/public/work.js:689` |
715
715
  | `582bdd9435eb` | certain | Select task {…} for bulk actions | `modules/hall-ui/public/work.js:341` |
716
716
  | `d91c8e9be76c` | certain | Select task {…} for bulk claim | `modules/hall-ui/public/goals-page.js:575` |
717
717
  | `7e1d54119e08` | certain | Select task {…} for bulk release | `modules/hall-ui/public/work.js:174` |
@@ -727,8 +727,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
727
727
  | `62c3ea026095` | certain | Settings sections | `modules/hall-ui/public/settings.html:43` |
728
728
  | `2566a43904cb` | certain | Settings — {{worldName}} | `modules/hall-ui/public/settings.html:6` |
729
729
  | `2566a43904cb` | certain | Settings — {{worldName}} | `modules/hall-ui/public/settings.html:6` |
730
- | `ac44b08aec92` | certain | Ship it | `modules/hall-ui/public/task.js:243` |
731
- | `6374d6172678` | certain | Shipped {…}{…}. | `modules/hall-ui/public/task.js:228` |
730
+ | `ac44b08aec92` | certain | Ship it | `modules/hall-ui/public/task.js:249` |
731
+ | `6374d6172678` | certain | Shipped {…}{…}. | `modules/hall-ui/public/task.js:234` |
732
732
  | `14d32a35c15f` | certain | Show my cross-project record | `modules/hall-ui/public/settings.js:579` |
733
733
  | `dc0f9fe50a65` | certain | Show the setup guide again | `modules/hall-ui/public/index.html:55` |
734
734
  | `2f12d46f96ca` | certain | Sign in from the app. | `modules/hall-ui/public/builders.js:984` |
@@ -759,14 +759,14 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
759
759
  | `1e40f33483eb` | certain | Switch theme | `modules/hall-ui/public/shell.js:310` |
760
760
  | `93fa2e97dd35` | certain | System default for this skill | `modules/hall-ui/public/settings.js:74` |
761
761
  | `1cc5e12dde31` | certain | System oversight. Every panel below is Archon-only. | `modules/hall-ui/public/watch.js:897` |
762
- | `5f45e431346f` | certain | Task #{…} | `modules/hall-ui/public/task.js:170` |
762
+ | `5f45e431346f` | certain | Task #{…} | `modules/hall-ui/public/task.js:176` |
763
763
  | `dfc967a63d57` | certain | Task lifecycle from backlog to shipped, showing states and transitions and the edge where credits are awarded. | `modules/hall-ui/public/diagrams.html:60` |
764
764
  | `10cc12f37636` | certain | Task sections | `modules/hall-ui/public/work.html:48` |
765
765
  | `0e636ea41b29` | certain | Task status | `modules/hall-ui/public/goals-page.js:576` |
766
766
  | `af527fbc48e1` | certain | Task that carried the fix | `modules/hall-ui/public/copy-desk.html:120` |
767
767
  | `1d714be820d3` | certain | Task — {{worldName}} | `modules/hall-ui/public/task.html:6` |
768
768
  | `1d714be820d3` | certain | Task — {{worldName}} | `modules/hall-ui/public/task.html:6` |
769
- | `9da280e09b11` | certain | Tasks are numbered separately from GitHub pull requests, so this may be a PR rather than a GDS task. | `modules/hall-ui/public/task.js:293` |
769
+ | `9da280e09b11` | certain | Tasks are numbered separately from GitHub pull requests, so this may be a PR rather than a GDS task. | `modules/hall-ui/public/task.js:299` |
770
770
  | `860fa4af9917` | certain | Tasks could not be loaded. | `modules/hall-ui/public/goals-page.js:1398` |
771
771
  | `2fc66e722e33` | certain | Tasks open once you have read the builder primer. | `modules/hall-ui/public/work.html:38` |
772
772
  | `44579eef0c8d` | certain | Tasks — {{worldName}} | `modules/hall-ui/public/work.html:6` |
@@ -807,9 +807,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
807
807
  | `e9a14eab8e96` | certain | The sounds could not be loaded. Reload the page to try again. | `modules/hall-ui/public/settings.js:271` |
808
808
  | `cd18eed7e907` | certain | The string this flag names is no longer in the registry — it was edited or removed. Probably already fixed; co | `modules/hall-ui/public/copy-desk.js:63` |
809
809
  | `7d016f4a65bf` | certain | The system is mid-build. These diagrams deliberately separate what stands today from what is yet planned, so t | `modules/hall-ui/public/diagrams.html:49` |
810
- | `34555793f33e` | certain | The task list could not be loaded right now. | `modules/hall-ui/public/work.js:1097` |
810
+ | `34555793f33e` | certain | The task list could not be loaded right now. | `modules/hall-ui/public/work.js:1106` |
811
811
  | `a42a37c43bfb` | certain | The words this project shows people — what has been flagged, and what nobody has looked at. | `modules/hall-ui/public/copy-desk.js:218` |
812
- | `bcdbded93d4e` | certain | The work board failed to load. Reload to try again. | `modules/hall-ui/public/work.js:1266` |
812
+ | `bcdbded93d4e` | certain | The work board failed to load. Reload to try again. | `modules/hall-ui/public/work.js:1275` |
813
813
  | `25794c439321` | certain | Then copy the project onto your machine and run the one-shot bootstrap (it checks your setup, installs depende | `modules/hall-ui/public/builders.js:1051` |
814
814
  | `df316c3484de` | certain | Then drive it however you like: | `modules/hall-ui/public/builders.js:984` |
815
815
  | `6e46811189db` | certain | This PR is held by the gate-review check. | `modules/hall-ui/public/gate.js:113` |
@@ -838,7 +838,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
838
838
  | `c19344f5ce38` | certain | Tool errs | `modules/hall-ui/public/sessions.html:48` |
839
839
  | `2059342a3490` | certain | Totals by builder | `modules/hall-ui/public/watch.js:576` |
840
840
  | `77db3684aba9` | certain | Tracked for transparency — not charged in the early stage. | `modules/hall-ui/public/box-panel.js:237` |
841
- | `b6e04e9bc86f` | certain | Try reloading in a moment. | `modules/hall-ui/public/task.js:303` |
841
+ | `b6e04e9bc86f` | certain | Try reloading in a moment. | `modules/hall-ui/public/task.js:309` |
842
842
  | `1a64679fbb42` | certain | Typo or grammar | `modules/hall-ui/public/copy-desk.html:96` |
843
843
  | `2c1c20785a6e` | certain | Unclear — a person would not know what to do | `modules/hall-ui/public/copy-desk.html:93` |
844
844
  | `aa445f06cc5e` | certain | Unlink failed: {…} | `modules/hall-ui/public/settings.js:843` |
@@ -858,7 +858,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
858
858
  | `c1fcfa9b48c2` | certain | Watch — {{worldName}} | `modules/hall-ui/public/watch.html:6` |
859
859
  | `c1fcfa9b48c2` | certain | Watch — {{worldName}} | `modules/hall-ui/public/watch.html:6` |
860
860
  | `0658f0358ffd` | certain | Welcome back, {…}. | `modules/hall-ui/public/builders.js:790` |
861
- | `04ef2f1bc4c4` | certain | Welcome, {…}. Claim and release tasks and follow work in progress — no terminal needed. | `modules/hall-ui/public/work.js:1034` |
861
+ | `04ef2f1bc4c4` | certain | Welcome, {…}. Claim and release tasks and follow work in progress — no terminal needed. | `modules/hall-ui/public/work.js:1043` |
862
862
  | `f3d93a872a38` | certain | What counts | `modules/hall-ui/public/drachmae.js:68` |
863
863
  | `4a33938611be` | certain | What each builder's dev box has cost — spin-up, compute, and storage. Tracked for oversight; not charged in th | `modules/hall-ui/public/watch.html:87` |
864
864
  | `0874800c694a` | certain | What is being built right now. See | `modules/hall-ui/public/work.html:73` |
@@ -891,8 +891,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
891
891
  | `46b1265ef172` | certain | You are not a member of this goal. | `modules/hall-ui/public/goals-page.js:1505` |
892
892
  | `b31fc908c962` | certain | You claimed #{…}. Open a terminal to start work. | `modules/hall-ui/public/goals-page.js:674` |
893
893
  | `b31fc908c962` | certain | You claimed #{…}. Open a terminal to start work. | `modules/hall-ui/public/goals-page.js:926` |
894
- | `b31fc908c962` | certain | You claimed #{…}. Open a terminal to start work. | `modules/hall-ui/public/work.js:747` |
895
- | `b31fc908c962` | certain | You claimed #{…}. Open a terminal to start work. | `modules/hall-ui/public/work.js:812` |
894
+ | `b31fc908c962` | certain | You claimed #{…}. Open a terminal to start work. | `modules/hall-ui/public/work.js:751` |
895
+ | `b31fc908c962` | certain | You claimed #{…}. Open a terminal to start work. | `modules/hall-ui/public/work.js:821` |
896
896
  | `3e5b3271bdb4` | certain | You have not voted on this item. Casting arrives with the vote form. | `modules/hall-ui/public/government.js:785` |
897
897
  | `6b759151f722` | certain | You have reached the end. The button below is now active. | `modules/hall-ui/public/primer.js:529` |
898
898
  | `6d5a4ca58dd6` | certain | You haven’t joined any goals yet. | `modules/hall-ui/public/goals.js:83` |
@@ -101,8 +101,8 @@
101
101
  "at": [
102
102
  "modules/hall-ui/public/goals-page.js:674",
103
103
  "modules/hall-ui/public/goals-page.js:926",
104
- "modules/hall-ui/public/work.js:747",
105
- "modules/hall-ui/public/work.js:812"
104
+ "modules/hall-ui/public/work.js:751",
105
+ "modules/hall-ui/public/work.js:821"
106
106
  ]
107
107
  },
108
108
  {
@@ -134,8 +134,8 @@
134
134
  "text": "Copy prompt",
135
135
  "occurrences": 3,
136
136
  "at": [
137
- "modules/hall-ui/public/task.js:252",
138
- "modules/hall-ui/public/task.js:269",
137
+ "modules/hall-ui/public/task.js:258",
138
+ "modules/hall-ui/public/task.js:275",
139
139
  "modules/hall-ui/public/work.js:446"
140
140
  ]
141
141
  },
@@ -179,8 +179,8 @@
179
179
  "occurrences": 3,
180
180
  "at": [
181
181
  "modules/hall-ui/public/goals-page.js:949",
182
- "modules/hall-ui/public/work.js:783",
183
- "modules/hall-ui/public/work.js:836"
182
+ "modules/hall-ui/public/work.js:792",
183
+ "modules/hall-ui/public/work.js:845"
184
184
  ]
185
185
  },
186
186
  {
@@ -385,7 +385,7 @@
385
385
  "occurrences": 2,
386
386
  "at": [
387
387
  "modules/hall-ui/public/goals-page.js:677",
388
- "modules/hall-ui/public/work.js:750"
388
+ "modules/hall-ui/public/work.js:754"
389
389
  ]
390
390
  },
391
391
  {
@@ -775,7 +775,7 @@
775
775
  "occurrences": 2,
776
776
  "at": [
777
777
  "modules/hall-ui/public/profile.js:144",
778
- "modules/hall-ui/public/work.js:905"
778
+ "modules/hall-ui/public/work.js:914"
779
779
  ]
780
780
  },
781
781
  {
@@ -795,7 +795,7 @@
795
795
  "occurrences": 2,
796
796
  "at": [
797
797
  "modules/hall-ui/public/goals-page.js:702",
798
- "modules/hall-ui/public/work.js:954"
798
+ "modules/hall-ui/public/work.js:963"
799
799
  ]
800
800
  },
801
801
  {
@@ -915,7 +915,7 @@
915
915
  "occurrences": 2,
916
916
  "at": [
917
917
  "modules/hall-ui/public/goals-page.js:944",
918
- "modules/hall-ui/public/work.js:828"
918
+ "modules/hall-ui/public/work.js:837"
919
919
  ]
920
920
  },
921
921
  {
@@ -1519,7 +1519,7 @@
1519
1519
  "surface": "builders-hall",
1520
1520
  "text": ", follow its acceptance criteria, stay within touches[], /builder-ship",
1521
1521
  "file": "modules/hall-ui/public/work.js",
1522
- "line": 735,
1522
+ "line": 739,
1523
1523
  "origin": "js-markup",
1524
1524
  "confidence": "certain"
1525
1525
  },
@@ -2032,7 +2032,7 @@
2032
2032
  "surface": "builders-hall",
2033
2033
  "text": "Awaiting the grader / a confirmation before it can ship.",
2034
2034
  "file": "modules/hall-ui/public/task.js",
2035
- "line": 247,
2035
+ "line": 253,
2036
2036
  "origin": "js-markup",
2037
2037
  "confidence": "certain"
2038
2038
  },
@@ -2311,7 +2311,7 @@
2311
2311
  "surface": "builders-hall",
2312
2312
  "text": "Checking dependency order…",
2313
2313
  "file": "modules/hall-ui/public/work.js",
2314
- "line": 696,
2314
+ "line": 700,
2315
2315
  "origin": "js-text-assign",
2316
2316
  "confidence": "certain"
2317
2317
  },
@@ -2320,7 +2320,7 @@
2320
2320
  "surface": "builders-hall",
2321
2321
  "text": "Checking for conflicts…",
2322
2322
  "file": "modules/hall-ui/public/work.js",
2323
- "line": 675,
2323
+ "line": 679,
2324
2324
  "origin": "js-text-assign",
2325
2325
  "confidence": "certain"
2326
2326
  },
@@ -2401,7 +2401,7 @@
2401
2401
  "surface": "builders-hall",
2402
2402
  "text": "Claimed {…} tasks. Open a terminal to start work.",
2403
2403
  "file": "modules/hall-ui/public/work.js",
2404
- "line": 750,
2404
+ "line": 754,
2405
2405
  "origin": "js-notice",
2406
2406
  "confidence": "certain"
2407
2407
  },
@@ -2608,7 +2608,7 @@
2608
2608
  "surface": "builders-hall",
2609
2609
  "text": "Confirm that verification for #{…} actually passed?",
2610
2610
  "file": "modules/hall-ui/public/task.js",
2611
- "line": 284,
2611
+ "line": 290,
2612
2612
  "origin": "js-notice",
2613
2613
  "confidence": "certain"
2614
2614
  },
@@ -2743,7 +2743,7 @@
2743
2743
  "surface": "builders-hall",
2744
2744
  "text": "Copy prompt",
2745
2745
  "file": "modules/hall-ui/public/task.js",
2746
- "line": 252,
2746
+ "line": 258,
2747
2747
  "origin": "js-markup",
2748
2748
  "confidence": "certain"
2749
2749
  },
@@ -2752,7 +2752,7 @@
2752
2752
  "surface": "builders-hall",
2753
2753
  "text": "Copy prompt",
2754
2754
  "file": "modules/hall-ui/public/task.js",
2755
- "line": 269,
2755
+ "line": 275,
2756
2756
  "origin": "js-text-assign",
2757
2757
  "confidence": "certain"
2758
2758
  },
@@ -2950,7 +2950,7 @@
2950
2950
  "surface": "builders-hall",
2951
2951
  "text": "Could not load #{…}",
2952
2952
  "file": "modules/hall-ui/public/task.js",
2953
- "line": 303,
2953
+ "line": 309,
2954
2954
  "origin": "js-markup",
2955
2955
  "confidence": "certain"
2956
2956
  },
@@ -4147,7 +4147,7 @@
4147
4147
  "surface": "builders-hall",
4148
4148
  "text": "Goal #{…}",
4149
4149
  "file": "modules/hall-ui/public/task.js",
4150
- "line": 196,
4150
+ "line": 202,
4151
4151
  "origin": "js-markup",
4152
4152
  "confidence": "certain"
4153
4153
  },
@@ -4723,7 +4723,7 @@
4723
4723
  "surface": "builders-hall",
4724
4724
  "text": "Last claimed by",
4725
4725
  "file": "modules/hall-ui/public/task.js",
4726
- "line": 207,
4726
+ "line": 213,
4727
4727
  "origin": "js-markup",
4728
4728
  "confidence": "certain"
4729
4729
  },
@@ -5560,7 +5560,7 @@
5560
5560
  "surface": "builders-hall",
5561
5561
  "text": "Not found",
5562
5562
  "file": "modules/hall-ui/public/task.js",
5563
- "line": 298,
5563
+ "line": 304,
5564
5564
  "origin": "js-text-assign",
5565
5565
  "confidence": "certain"
5566
5566
  },
@@ -5632,7 +5632,7 @@
5632
5632
  "surface": "builders-hall",
5633
5633
  "text": "Nothing in the backlog right now.",
5634
5634
  "file": "modules/hall-ui/public/work.js",
5635
- "line": 944,
5635
+ "line": 953,
5636
5636
  "origin": "js-markup",
5637
5637
  "confidence": "certain"
5638
5638
  },
@@ -5659,7 +5659,7 @@
5659
5659
  "surface": "builders-hall",
5660
5660
  "text": "Nothing shipped yet.",
5661
5661
  "file": "modules/hall-ui/public/work.js",
5662
- "line": 905,
5662
+ "line": 914,
5663
5663
  "origin": "js-markup",
5664
5664
  "confidence": "certain"
5665
5665
  },
@@ -5794,7 +5794,7 @@
5794
5794
  "surface": "builders-hall",
5795
5795
  "text": "Open task #{…}",
5796
5796
  "file": "modules/hall-ui/public/work.js",
5797
- "line": 954,
5797
+ "line": 963,
5798
5798
  "origin": "js-markup",
5799
5799
  "confidence": "certain"
5800
5800
  },
@@ -5839,7 +5839,7 @@
5839
5839
  "surface": "builders-hall",
5840
5840
  "text": "Open the Work Board",
5841
5841
  "file": "modules/hall-ui/public/task.js",
5842
- "line": 252,
5842
+ "line": 258,
5843
5843
  "origin": "js-markup",
5844
5844
  "confidence": "certain"
5845
5845
  },
@@ -6352,7 +6352,7 @@
6352
6352
  "surface": "builders-hall",
6353
6353
  "text": "Recent history could not be loaded right now.",
6354
6354
  "file": "modules/hall-ui/public/work.js",
6355
- "line": 1043,
6355
+ "line": 1052,
6356
6356
  "origin": "js-markup",
6357
6357
  "confidence": "certain"
6358
6358
  },
@@ -6433,7 +6433,7 @@
6433
6433
  "surface": "builders-hall",
6434
6434
  "text": "Release your claim on #{…}? It returns to the queue and no {…} are earned.",
6435
6435
  "file": "modules/hall-ui/public/work.js",
6436
- "line": 828,
6436
+ "line": 837,
6437
6437
  "origin": "js-notice",
6438
6438
  "confidence": "certain"
6439
6439
  },
@@ -6442,7 +6442,7 @@
6442
6442
  "surface": "builders-hall",
6443
6443
  "text": "Release {…}? {…} to the queue and no {…} are earned.",
6444
6444
  "file": "modules/hall-ui/public/work.js",
6445
- "line": 777,
6445
+ "line": 786,
6446
6446
  "origin": "js-notice",
6447
6447
  "confidence": "certain"
6448
6448
  },
@@ -6460,7 +6460,7 @@
6460
6460
  "surface": "builders-hall",
6461
6461
  "text": "Released #{…}. It returns to the queue.",
6462
6462
  "file": "modules/hall-ui/public/work.js",
6463
- "line": 783,
6463
+ "line": 792,
6464
6464
  "origin": "js-notice",
6465
6465
  "confidence": "certain"
6466
6466
  },
@@ -6469,7 +6469,7 @@
6469
6469
  "surface": "builders-hall",
6470
6470
  "text": "Released #{…}. It returns to the queue.",
6471
6471
  "file": "modules/hall-ui/public/work.js",
6472
- "line": 836,
6472
+ "line": 845,
6473
6473
  "origin": "js-notice",
6474
6474
  "confidence": "certain"
6475
6475
  },
@@ -6937,7 +6937,7 @@
6937
6937
  "surface": "builders-hall",
6938
6938
  "text": "Select at least 2 waiting tasks to copy a parallel-session prompt.",
6939
6939
  "file": "modules/hall-ui/public/work.js",
6940
- "line": 660,
6940
+ "line": 664,
6941
6941
  "origin": "js-text-assign",
6942
6942
  "confidence": "certain"
6943
6943
  },
@@ -6946,7 +6946,7 @@
6946
6946
  "surface": "builders-hall",
6947
6947
  "text": "Select at least 2 waiting tasks to copy a sequential prompt.",
6948
6948
  "file": "modules/hall-ui/public/work.js",
6949
- "line": 685,
6949
+ "line": 689,
6950
6950
  "origin": "js-text-assign",
6951
6951
  "confidence": "certain"
6952
6952
  },
@@ -7090,7 +7090,7 @@
7090
7090
  "surface": "builders-hall",
7091
7091
  "text": "Ship it",
7092
7092
  "file": "modules/hall-ui/public/task.js",
7093
- "line": 243,
7093
+ "line": 249,
7094
7094
  "origin": "js-markup",
7095
7095
  "confidence": "certain"
7096
7096
  },
@@ -7099,7 +7099,7 @@
7099
7099
  "surface": "builders-hall",
7100
7100
  "text": "Shipped {…}{…}.",
7101
7101
  "file": "modules/hall-ui/public/task.js",
7102
- "line": 228,
7102
+ "line": 234,
7103
7103
  "origin": "js-markup",
7104
7104
  "confidence": "certain"
7105
7105
  },
@@ -7378,7 +7378,7 @@
7378
7378
  "surface": "builders-hall",
7379
7379
  "text": "Task #{…}",
7380
7380
  "file": "modules/hall-ui/public/task.js",
7381
- "line": 170,
7381
+ "line": 176,
7382
7382
  "origin": "js-text-assign",
7383
7383
  "confidence": "certain"
7384
7384
  },
@@ -7441,7 +7441,7 @@
7441
7441
  "surface": "builders-hall",
7442
7442
  "text": "Tasks are numbered separately from GitHub pull requests, so this may be a PR rather than a GDS task.",
7443
7443
  "file": "modules/hall-ui/public/task.js",
7444
- "line": 293,
7444
+ "line": 299,
7445
7445
  "origin": "js-markup",
7446
7446
  "confidence": "certain"
7447
7447
  },
@@ -7810,7 +7810,7 @@
7810
7810
  "surface": "builders-hall",
7811
7811
  "text": "The task list could not be loaded right now.",
7812
7812
  "file": "modules/hall-ui/public/work.js",
7813
- "line": 1097,
7813
+ "line": 1106,
7814
7814
  "origin": "js-markup",
7815
7815
  "confidence": "certain"
7816
7816
  },
@@ -7828,7 +7828,7 @@
7828
7828
  "surface": "builders-hall",
7829
7829
  "text": "The work board failed to load. Reload to try again.",
7830
7830
  "file": "modules/hall-ui/public/work.js",
7831
- "line": 1266,
7831
+ "line": 1275,
7832
7832
  "origin": "js-notice",
7833
7833
  "confidence": "certain"
7834
7834
  },
@@ -8089,7 +8089,7 @@
8089
8089
  "surface": "builders-hall",
8090
8090
  "text": "Try reloading in a moment.",
8091
8091
  "file": "modules/hall-ui/public/task.js",
8092
- "line": 303,
8092
+ "line": 309,
8093
8093
  "origin": "js-markup",
8094
8094
  "confidence": "certain"
8095
8095
  },
@@ -8269,7 +8269,7 @@
8269
8269
  "surface": "builders-hall",
8270
8270
  "text": "Welcome, {…}. Claim and release tasks and follow work in progress — no terminal needed.",
8271
8271
  "file": "modules/hall-ui/public/work.js",
8272
- "line": 1034,
8272
+ "line": 1043,
8273
8273
  "origin": "js-text-assign",
8274
8274
  "confidence": "certain"
8275
8275
  },
@@ -8566,7 +8566,7 @@
8566
8566
  "surface": "builders-hall",
8567
8567
  "text": "You claimed #{…}. Open a terminal to start work.",
8568
8568
  "file": "modules/hall-ui/public/work.js",
8569
- "line": 747,
8569
+ "line": 751,
8570
8570
  "origin": "js-notice",
8571
8571
  "confidence": "certain"
8572
8572
  },
@@ -8575,7 +8575,7 @@
8575
8575
  "surface": "builders-hall",
8576
8576
  "text": "You claimed #{…}. Open a terminal to start work.",
8577
8577
  "file": "modules/hall-ui/public/work.js",
8578
- "line": 812,
8578
+ "line": 821,
8579
8579
  "origin": "js-notice",
8580
8580
  "confidence": "certain"
8581
8581
  },
@@ -230,8 +230,48 @@
230
230
  return { label: label || stripMd(raw).slice(0, 80), detail };
231
231
  }
232
232
 
233
+
234
+ // ---- ADR 0116 error envelope (task 1002462) -------------------------------
235
+ //
236
+ // The server returns `{ error: { code, message, details } }` via res.fail().
237
+ // The code is NESTED, so a bare `data.error === 'CODE'` test compares a string
238
+ // to an OBJECT and silently never matches: every switch falls through to its
239
+ // generic default. That degrades into a wrong-but-plausible toast rather than a
240
+ // visible break, so no smoke test catches it — which is how the same defect
241
+ // survived independently across four hall surfaces (work.js, task.js, and
242
+ // hand-rolled copies in goals-page.js and task-detail.js).
243
+ //
244
+ // These live here, in the shared toolkit every hall page already loads first,
245
+ // so a fifth copy is never the easiest option. They take the RESPONSE BODY —
246
+ // callers pass `err.data` — and each accepts BOTH the envelope and the
247
+ // pre-envelope flat shape `{ error: 'CODE', ...fields }`, so an older server
248
+ // still maps. Pure: no DOM, no network, no page-specific behaviour (unlike the
249
+ // network helpers, which are deliberately NOT in this file).
250
+ function errCode(data) {
251
+ const e = data && data.error;
252
+ if (e && typeof e === 'object') return e.code || '';
253
+ if (typeof e === 'string') return e;
254
+ return (data && data.code) || '';
255
+ }
256
+ function errMessage(data) {
257
+ const e = data && data.error;
258
+ if (e && typeof e === 'object' && e.message) return e.message;
259
+ return (data && data.message) || '';
260
+ }
261
+ // Structured payload. Falls back to the BODY itself on the flat shape, where
262
+ // the extra fields (conflicts, failures, what_to_do) sat at the top level.
263
+ function errDetails(data) {
264
+ const e = data && data.error;
265
+ if (e && typeof e === 'object' && e.details && typeof e.details === 'object') return e.details;
266
+ // ALWAYS an object, so every caller can read `det.conflicts` with no type
267
+ // guard. A non-object body (a string, a number) would otherwise leak through
268
+ // and turn a detail read into undefined-or-worse at the call site.
269
+ return (data && typeof data === 'object') ? data : {};
270
+ }
271
+
233
272
  window.OTB = {
234
273
  escapeHtml, $, fmtNum, num, fmtInt, fmtCompact, fmtDate, rankLabel, toast, moduleOn,
274
+ errCode, errMessage, errDetails, // task 1002462 — ADR 0116 envelope readers
235
275
  contributeSettingsPanel, settingsPanels,
236
276
  contributeHallWidget, hallWidgets, hallWidgetIds,
237
277
  splitCriterion,
@@ -21,7 +21,7 @@
21
21
  // builds through unchanged; result-mode ({ status, ok, data }) preserves control flow 1:1.
22
22
  const api = window.BongosClient.createClient({ baseUrl: '', credentials: 'same-origin', throwOnError: false });
23
23
  const AUTH_NEEDED = 'auth-needed';
24
- const { escapeHtml, $, fmtDate } = window.OTB;
24
+ const { escapeHtml, $, fmtDate, errCode, errMessage } = window.OTB; // task 1002462: envelope readers
25
25
  const toast = (msg) => window.OTB.toast(msg, { duration: 2600 });
26
26
  const curLabel = () => (window.__BRANDING__ && window.__BRANDING__.currency && window.__BRANDING__.currency.label) || 'credits';
27
27
 
@@ -70,13 +70,19 @@
70
70
  // exactly those POST /tasks/:id/ship + /confirm can return. The server is the
71
71
  // authority (ADR 0016); the UI only surfaces the refusal.
72
72
  function friendlyActionError(status, data) {
73
- switch (data && data.error) {
73
+ // task 1002462: read the ADR 0116 envelope. `data.error` is an OBJECT here,
74
+ // so every case fell through to the generic default and a precise lifecycle
75
+ // refusal ("not confirmed yet", "attestation required") rendered as
76
+ // "Could not complete that (409)".
77
+ switch (errCode(data)) {
74
78
  case 'task_not_confirmed':
75
79
  return 'That task can only be shipped once it is confirmed (its grade has landed).';
76
80
  case 'task_not_completed':
77
81
  return 'That task is not marked complete yet.';
78
82
  case 'verify_attestation_required':
79
- return (data && data.message) || 'Confirm a verification task only after the verify actually passed.';
83
+ // The server's own sentence is the useful one — it names the task and the
84
+ // flag. It sits at error.message under the envelope, not data.message.
85
+ return errMessage(data) || 'Confirm a verification task only after the verify actually passed.';
80
86
  case 'rank_too_low_for_task':
81
87
  case 'INSUFFICIENT_RANK':
82
88
  return 'Your rank is not high enough for that action.';
@@ -35,7 +35,7 @@
35
35
  // window.OTB toolkit (dom-utils.js, loaded first). Thin wrappers keep this
36
36
  // file's exact variants (date-only fmtDate; a 2200ms clearing toast).
37
37
  // fmtAgo / toAuth / getJSON / postJSON stay local below.
38
- const { escapeHtml, $, fmtNum } = window.OTB;
38
+ const { escapeHtml, $, fmtNum, errCode, errDetails } = window.OTB; // task 1002462: envelope readers
39
39
  // Shared task-domain helpers (task 1002463). These lived in two copies here and
40
40
  // in the other board and had already drifted — goals-page.js had silently lost
41
41
  // friendlyBatchReason's MODULE_CONFLICT case. Destructured so every call site
@@ -468,14 +468,18 @@
468
468
  // Map the server's typed error code to a builder-readable line. The codes are
469
469
  // exactly those POST /claims and POST /claims/:id/resolve can return.
470
470
  function friendlyActionError(status, data) {
471
- const code = data && data.error;
472
- switch (code) {
471
+ // task 1002462: read the ADR 0116 envelope. `data.error` is an OBJECT, so the
472
+ // old `const code = data && data.error` compared a string to an object and
473
+ // EVERY case below fell through to the generic default — a wrong-but-plausible
474
+ // toast on every claim/release refusal.
475
+ const det = errDetails(data);
476
+ switch (errCode(data)) {
473
477
  case 'ALREADY_CLAIMED':
474
478
  return 'Someone else claimed that task first. The board will refresh.';
475
479
  case 'TASK_NOT_READY':
476
480
  return 'That task is no longer ready to be claimed.';
477
481
  case 'TOUCHES_CONFLICT': {
478
- const titles = Array.isArray(data.conflicts) ? data.conflicts.map((c) => c.title).filter(Boolean) : [];
482
+ const titles = Array.isArray(det.conflicts) ? det.conflicts.map((c) => c.title).filter(Boolean) : [];
479
483
  return titles.length
480
484
  ? `That task overlaps an active claim: ${titles.join('; ')}. Wait for it to ship.`
481
485
  : 'That task overlaps another active claim. Wait for it to ship.';
@@ -487,7 +491,7 @@
487
491
  case 'INSUFFICIENT_RANK':
488
492
  return 'Your rank is not yet high enough for that task.';
489
493
  case 'newcomer_must_ship_first':
490
- return data.what_to_do || 'Ship your current claim before opening another.';
494
+ return det.what_to_do || 'Ship your current claim before opening another.';
491
495
  case 'NOT_YOUR_CLAIM':
492
496
  return 'That claim is not yours to release.';
493
497
  case 'ALREADY_RESOLVED':
@@ -753,8 +757,13 @@
753
757
  await refreshLive();
754
758
  } catch (err) {
755
759
  if (err && err.message === 'redirecting to auth') return;
756
- if (err.status === 409 && err.data && err.data.error === 'batch_failed') {
757
- const failures = Array.isArray(err.data.failures) ? err.data.failures : [];
760
+ // task 1002462: same envelope defect — this tested `err.data.error === 'batch_failed'`
761
+ // against an object, so an all-or-nothing batch refusal rendered as the generic toast
762
+ // and the per-task reasons were dropped on the floor.
763
+ if (err.status === 409 && errCode(err.data) === 'batch_failed') {
764
+ const bdet = errDetails(err.data);
765
+ const failures = Array.isArray(bdet.failures) ? bdet.failures
766
+ : (Array.isArray(err.data && err.data.failures) ? err.data.failures : []);
758
767
  const lines = failures.map((f) => `#${f.task_id} (${friendlyBatchReason(f)})`);
759
768
  toast(lines.length
760
769
  ? `The batch could not be claimed — ${lines.join('; ')}.`
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.272",
3
+ "version": "1.19.273",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.272",
9
+ "version": "1.19.273",
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.272",
3
+ "version": "1.19.273",
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
@@ -971,8 +971,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
971
971
  // landed since 1.19.270 with no explicit bump. run 32437463473. (task 1002620)
972
972
  // 1.19.272 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
973
973
  // landed since 1.19.271 with no explicit bump. run 32438140524. (task 1002620)
974
+ // 1.19.273 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
975
+ // landed since 1.19.272 with no explicit bump. run 32441024959. (task 1002620)
974
976
  // ---------------------------------------------------------------------------
975
- const CORE_VERSION = '1.19.272'; // CI auto-patch carrier (ADR 0161); see changelog above
977
+ const CORE_VERSION = '1.19.273'; // CI auto-patch carrier (ADR 0161); see changelog above
976
978
 
977
979
  // A namespaced logger so a module's log lines are attributable + consistent.
978
980
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -0,0 +1,264 @@
1
+ // tests/hall_error_envelope.mjs — task 1002462.
2
+ //
3
+ // THE DEFECT. The server returns the ADR 0116 envelope via res.fail():
4
+ // `{ error: { code, message, details } }`. The code is NESTED, so a bare
5
+ // `data.error === 'CODE'` test compares a string to an OBJECT and silently never
6
+ // matches — every switch falls through to its generic default. The builder gets
7
+ // "Could not complete that (409). Try again." for a refusal the server described
8
+ // precisely.
9
+ //
10
+ // It survived because it degrades into a wrong-but-PLAUSIBLE toast rather than a
11
+ // visible break, so nothing failed and no smoke test could catch it. The same
12
+ // defect appeared independently on four hall surfaces.
13
+ //
14
+ // The fix puts the readers in dom-utils.js — the shared toolkit every hall page
15
+ // already loads first — so a fifth copy is never the easiest option.
16
+ //
17
+ // What we prove, executing the REAL files in a vm (the tests/hall_signout.mjs and
18
+ // goal_criterion_confirm_ui.mjs precedent — there is no jsdom here):
19
+ // 1. dom-utils' errCode / errMessage / errDetails read BOTH wire shapes and
20
+ // survive hostile input. This is now the single point of failure for four
21
+ // surfaces, so it is tested directly rather than through a page.
22
+ // 2. END TO END on the real task.js: a 409 carrying the envelope renders the
23
+ // SERVER'S OWN sentence in the toast, not the generic fallback. This is the
24
+ // user-visible regression, driven through a real button click.
25
+ // 3. Neither consumer still reads the flat shape anywhere.
26
+ //
27
+ // Run: node tests/hall_error_envelope.mjs
28
+
29
+ import assert from 'node:assert/strict';
30
+ import fs from 'node:fs';
31
+ import path from 'node:path';
32
+ import vm from 'node:vm';
33
+ import { fileURLToPath } from 'node:url';
34
+
35
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
36
+ const HALL = path.join(ROOT, 'modules/hall-ui/public');
37
+
38
+ let passed = 0;
39
+ let failed = 0;
40
+ function t(name, fn) {
41
+ try {
42
+ const r = fn();
43
+ if (r && typeof r.then === 'function') {
44
+ return r.then(
45
+ () => { passed++; console.log(` ok ${name}`); },
46
+ (e) => { failed++; console.log(` FAIL ${name}`); console.log(` ${e.message}`); }
47
+ );
48
+ }
49
+ passed++; console.log(` ok ${name}`);
50
+ } catch (e) {
51
+ failed++; console.log(` FAIL ${name}`); console.log(` ${e.message}`);
52
+ }
53
+ return Promise.resolve();
54
+ }
55
+
56
+ // ---- 1. the shared readers, from the real dom-utils.js ----------------------
57
+
58
+ function loadOTB() {
59
+ const sandbox = {
60
+ window: {},
61
+ document: {
62
+ createElement: () => ({ style: {}, classList: { add() {}, remove() {} }, appendChild() {}, remove() {} }),
63
+ body: { appendChild() {} },
64
+ querySelector: () => null,
65
+ querySelectorAll: () => [],
66
+ getElementById: () => null,
67
+ },
68
+ setTimeout, clearTimeout, console,
69
+ };
70
+ sandbox.globalThis = sandbox;
71
+ vm.createContext(sandbox);
72
+ vm.runInContext(fs.readFileSync(path.join(HALL, 'dom-utils.js'), 'utf8'), sandbox, { filename: 'dom-utils.js' });
73
+ return sandbox.window.OTB;
74
+ }
75
+
76
+ await t('dom-utils exports the envelope readers on window.OTB', () => {
77
+ const OTB = loadOTB();
78
+ for (const fn of ['errCode', 'errMessage', 'errDetails']) {
79
+ assert.equal(typeof OTB[fn], 'function', `${fn} must be on the shared toolkit`);
80
+ }
81
+ });
82
+
83
+ await t('errCode reads the ADR 0116 envelope AND the legacy flat shape', () => {
84
+ const { errCode } = loadOTB();
85
+ assert.equal(errCode({ error: { code: 'ALREADY_CLAIMED', message: 'x' } }), 'ALREADY_CLAIMED');
86
+ assert.equal(errCode({ error: 'ALREADY_CLAIMED' }), 'ALREADY_CLAIMED', 'an older server must still map');
87
+ assert.equal(errCode({ code: 'ALREADY_CLAIMED' }), 'ALREADY_CLAIMED');
88
+ });
89
+
90
+ await t('errCode never returns an object — the whole bug in one assertion', () => {
91
+ const { errCode } = loadOTB();
92
+ const code = errCode({ error: { code: 'TOUCHES_CONFLICT', details: { conflicts: [] } } });
93
+ assert.equal(typeof code, 'string');
94
+ assert.notEqual(typeof code, 'object', 'returning the object is what made every switch case miss');
95
+ });
96
+
97
+ await t('errMessage prefers the envelope message over a top-level one', () => {
98
+ const { errMessage } = loadOTB();
99
+ assert.equal(errMessage({ error: { code: 'c', message: 'the real sentence' } }), 'the real sentence');
100
+ assert.equal(errMessage({ message: 'legacy sentence' }), 'legacy sentence');
101
+ assert.equal(errMessage({ error: 'c' }), '');
102
+ });
103
+
104
+ await t('errDetails takes error.details, else falls back to the BODY (flat shape)', () => {
105
+ const { errDetails } = loadOTB();
106
+ assert.deepEqual(errDetails({ error: { code: 'c', details: { conflicts: [{ title: 'A' }] } } }).conflicts, [{ title: 'A' }]);
107
+ // On the flat shape the extra fields sat at the top level.
108
+ assert.deepEqual(errDetails({ error: 'c', conflicts: [{ title: 'B' }] }).conflicts, [{ title: 'B' }]);
109
+ });
110
+
111
+ await t('the readers survive hostile / empty input without throwing', () => {
112
+ const { errCode, errMessage, errDetails } = loadOTB();
113
+ for (const bad of [undefined, null, {}, { error: null }, { error: 0 }, { error: [] }, 'str', 42]) {
114
+ assert.equal(typeof errCode(bad), 'string', `errCode(${JSON.stringify(bad)})`);
115
+ assert.equal(typeof errMessage(bad), 'string');
116
+ assert.equal(typeof errDetails(bad), 'object');
117
+ }
118
+ });
119
+
120
+ // ---- 2. end to end through the REAL task.js --------------------------------
121
+
122
+ // Minimal DOM: only what task.js touches (getElementById/querySelector by id,
123
+ // addEventListener, innerHTML, textContent). Elements are plain objects with a
124
+ // click() that invokes the registered handler.
125
+ // The DOM handlers call runLifecycle without returning its promise, so the toast
126
+ // lands several microtasks after the click. Flush rather than guess a timeout.
127
+ async function flush(n = 12) {
128
+ for (let i = 0; i < n; i += 1) await new Promise((r) => setImmediate(r));
129
+ }
130
+
131
+ function makeEl(id) {
132
+ return {
133
+ id, innerHTML: '', textContent: '', disabled: false, dataset: {}, style: {},
134
+ _handlers: {},
135
+ addEventListener(ev, fn) { this._handlers[ev] = fn; },
136
+ click() { return this._handlers.click && this._handlers.click(); },
137
+ querySelector: () => null,
138
+ querySelectorAll: () => [],
139
+ classList: { add() {}, remove() {}, toggle() {} },
140
+ setAttribute() {}, removeAttribute() {}, appendChild() {}, remove() {},
141
+ };
142
+ }
143
+
144
+ async function bootTaskPage({ task, failWith }) {
145
+ const els = new Map();
146
+ const el = (id) => {
147
+ const key = String(id).replace(/^#/, '');
148
+ if (!els.has(key)) els.set(key, makeEl(key));
149
+ return els.get(key);
150
+ };
151
+ const toasts = [];
152
+ const document = {
153
+ _ready: null,
154
+ // renderTask does document.title.split(' — ') — it must be a real string.
155
+ title: '#0 — task — Cloud Bongos',
156
+ addEventListener(ev, fn) { if (ev === 'DOMContentLoaded') this._ready = fn; },
157
+ getElementById: (id) => el(id),
158
+ querySelector: (sel) => el(sel),
159
+ querySelectorAll: () => [],
160
+ createElement: () => makeEl('tmp'),
161
+ body: makeEl('body'),
162
+ };
163
+ const sandbox = {
164
+ document,
165
+ console,
166
+ setTimeout,
167
+ clearTimeout,
168
+ location: { hostname: 'builders.example.com', pathname: `/task/${task.id}`, href: '', assign() {} },
169
+ window: {
170
+ OTBBranding: { taskCreditValue: () => null, taskCreditLabel: () => 'credits' },
171
+ confirm: () => true,
172
+ location: { hostname: 'builders.example.com', pathname: `/task/${task.id}`, assign() {} },
173
+ // The generated typed client's result mode: { status, ok, data }.
174
+ BongosClient: {
175
+ createClient: () => ({
176
+ request: async (method, urlPath) => {
177
+ if (method === 'GET' && urlPath.includes('/me')) {
178
+ return { ok: true, status: 200, data: { builder: { id: 1, rank: 'archon' } } };
179
+ }
180
+ if (method === 'GET') return { ok: true, status: 200, data: { task, last_claim: null } };
181
+ // The lifecycle POST — refuse it with the shape under test.
182
+ return { ok: false, status: failWith.status, data: failWith.body };
183
+ },
184
+ }),
185
+ },
186
+ },
187
+ };
188
+ sandbox.window.document = document;
189
+ sandbox.globalThis = sandbox;
190
+ vm.createContext(sandbox);
191
+ // dom-utils FIRST, in this same context — exactly the real page's script order,
192
+ // and required because dom-utils' `$` closes over the document it sees at
193
+ // definition time.
194
+ vm.runInContext(fs.readFileSync(path.join(HALL, 'dom-utils.js'), 'utf8'), sandbox, { filename: 'dom-utils.js' });
195
+ const realToast = sandbox.window.OTB.toast;
196
+ sandbox.window.OTB = { ...sandbox.window.OTB, toast: (m) => { toasts.push(String(m)); } };
197
+ void realToast;
198
+ vm.runInContext(fs.readFileSync(path.join(HALL, 'task.js'), 'utf8'), sandbox, { filename: 'task.js' });
199
+ assert.ok(document._ready, 'task.js registered a DOMContentLoaded handler');
200
+ await document._ready();
201
+ return { els, el, toasts };
202
+ }
203
+
204
+ const VERIFY_TASK = { id: 4242, kind: 'verify', title: 'a verify task', status: 'completed', description: 'x' };
205
+
206
+ await t('END TO END: a 409 envelope renders the SERVER\'S sentence, not the generic fallback', async () => {
207
+ const serverSentence = "Task #4242 is a verification task (kind='verify') — confirm it only AFTER the verification ran.";
208
+ const { el, toasts } = await bootTaskPage({
209
+ task: VERIFY_TASK,
210
+ failWith: {
211
+ status: 409,
212
+ body: { error: { code: 'verify_attestation_required', message: serverSentence, details: {} } },
213
+ },
214
+ });
215
+ const btn = el('confirm-btn');
216
+ assert.ok(btn._handlers.click, 'the confirm control rendered and is wired');
217
+ await btn.click();
218
+ await flush();
219
+ const shown = toasts.join(' | ');
220
+ assert.ok(
221
+ shown.includes(serverSentence),
222
+ `the toast must carry the server's own sentence. got: ${shown}`
223
+ );
224
+ assert.ok(
225
+ !/Could not complete that/.test(shown),
226
+ `the generic fallback is exactly the bug — got: ${shown}`
227
+ );
228
+ });
229
+
230
+ await t('END TO END: the legacy FLAT shape still maps (older server)', async () => {
231
+ const { el, toasts } = await bootTaskPage({
232
+ // status 'confirmed' + a supervisor is what renders the SHIP control.
233
+ task: { ...VERIFY_TASK, kind: 'feature', status: 'confirmed' },
234
+ failWith: { status: 409, body: { error: 'task_not_confirmed' } },
235
+ });
236
+ const btn = el('ship-btn');
237
+ assert.ok(btn._handlers.click, 'the ship control rendered');
238
+ await btn.click();
239
+ await flush();
240
+ const shown = toasts.join(' | ');
241
+ assert.match(shown, /only be shipped once it is confirmed/, `got: ${shown}`);
242
+ assert.ok(!/Could not complete that/.test(shown), `got: ${shown}`);
243
+ });
244
+
245
+ // ---- 3. no flat reads left in either consumer -------------------------------
246
+
247
+ await t('neither work.js nor task.js reads the flat error shape any more', () => {
248
+ for (const rel of ['work.js', 'task.js']) {
249
+ const src = fs.readFileSync(path.join(HALL, rel), 'utf8');
250
+ const code = src.split('\n').filter((l) => !l.trim().startsWith('//')).join('\n');
251
+ assert.doesNotMatch(code, /data\s*&&\s*data\.error\b/, `${rel}: still reads data.error directly`);
252
+ assert.doesNotMatch(code, /err\.data\.error\s*===/, `${rel}: still compares err.data.error to a string`);
253
+ assert.doesNotMatch(code, /\bdata\.conflicts\b/, `${rel}: still reads conflicts off the body`);
254
+ assert.doesNotMatch(code, /\bdata\.what_to_do\b/, `${rel}: still reads what_to_do off the body`);
255
+ // And it must pull the shared readers rather than redefine a fifth copy.
256
+ assert.match(src, /window\.OTB/, `${rel}: uses the shared toolkit`);
257
+ assert.match(src, /errCode/, `${rel}: goes through errCode`);
258
+ assert.doesNotMatch(code, /function errCode\s*\(/, `${rel}: must NOT define its own copy`);
259
+ }
260
+ });
261
+
262
+ console.log('');
263
+ console.log(`hall_error_envelope: ${passed} passed, ${failed} failed`);
264
+ process.exit(failed === 0 ? 0 : 1);