@bongos/core 1.19.905 → 1.19.906

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.905",
6
- "core_contract": "1.19.905",
7
- "source_commit": "dc5ca8cc91d1d88f957f722664f60778d2bdc4f1",
5
+ "core_version": "1.19.906",
6
+ "core_contract": "1.19.906",
7
+ "source_commit": "292f91e86ee9b852efe6c0e93158f5815ccdfa42",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-20T13:17:59.483Z",
9
+ "built_at": "2026-09-20T13:41:10.148Z",
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": "85790109607eeddc8439f8473f642747ed158cfb88a269f55222c30bc45016e5",
20
+ "tree_sha256": "160619c1eb4a21d556e0ed9151463e10b29b88a5aeb1249d213d371aaae5402a",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2632,7 +2632,7 @@
2632
2632
  {
2633
2633
  "path": "docs/module-api-changelog.md",
2634
2634
  "mode": "0000644",
2635
- "sha256": "ade94268540de319c8d071b7b70654fca4cb4bdd7bcfbbfe8ddca5710329545b"
2635
+ "sha256": "d329f2a3999d8bc88ce4715be5ee51d9e7a60ba0e0f0a9e06163c12ff94d87ba"
2636
2636
  },
2637
2637
  {
2638
2638
  "path": "docs/modules-contract.md",
@@ -4992,7 +4992,7 @@
4992
4992
  {
4993
4993
  "path": "modules/hall-ui/public/people.js",
4994
4994
  "mode": "0000644",
4995
- "sha256": "4740be7b7d28c8c3e4098054c63de85086265149f7024b15cff443d59283c087"
4995
+ "sha256": "37d7c9b14bb42a473ef7caf45f138cd87b01b976bb593d1fd2a0c82c94208539"
4996
4996
  },
4997
4997
  {
4998
4998
  "path": "modules/hall-ui/public/people.states.json",
@@ -7782,12 +7782,12 @@
7782
7782
  {
7783
7783
  "path": "package-lock.json",
7784
7784
  "mode": "0000644",
7785
- "sha256": "3b60452f407da16a6c09df92482e570ca061e920dd7537a6f2f84569a13e0545"
7785
+ "sha256": "6a2f94c668864dc88fdc003473496102838182e8d18636930537c32bd67c7e47"
7786
7786
  },
7787
7787
  {
7788
7788
  "path": "package.json",
7789
7789
  "mode": "0000644",
7790
- "sha256": "3af5e528e00f1047c76f56189ef168ea8c879f09762b735160b5c6d2e81f9d24"
7790
+ "sha256": "1ddcd43de722cb5eff00c36a440b0df181f1c8168a8c8b3193fc3d9a586afdbd"
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": "2489905dea4c9defd22089221f6dce7c522f9860e6b684c9e6cea03a2600a17d"
9785
+ "sha256": "4593c8749b7b52a5bb6116e0d3dbe6004dc24346bb79ca0a5757359e98dc259e"
9786
9786
  },
9787
9787
  {
9788
9788
  "path": "src/module-loader/catalog.js",
@@ -11672,7 +11672,7 @@
11672
11672
  {
11673
11673
  "path": "tests/hall_roster_world.mjs",
11674
11674
  "mode": "0000644",
11675
- "sha256": "191184eeaf40d8e10704ae57bfe1d58574f7b6053634d69844d47212bf05f18a"
11675
+ "sha256": "477ec31839036884ac0923a078e7cb1e60d37548c758e24701b338c1e8179c6a"
11676
11676
  },
11677
11677
  {
11678
11678
  "path": "tests/hall_sessions_ledger.mjs",
@@ -12512,7 +12512,7 @@
12512
12512
  {
12513
12513
  "path": "tests/people_directory_clip.mjs",
12514
12514
  "mode": "0000644",
12515
- "sha256": "b412cf076656c3400d76f46a2df18adb5a2ec376ed7e3da6beefcf344446993b"
12515
+ "sha256": "e3b2f36780b35fd66690b1c426832322b2781c5386cf7fd50e995a7c2cc089bb"
12516
12516
  },
12517
12517
  {
12518
12518
  "path": "tests/permission_path.mjs",
@@ -2284,5 +2284,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
2284
2284
  landed since 1.19.903 with no explicit bump. run 35511494246. (task 1002620)
2285
2285
  1.19.905 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2286
2286
  landed since 1.19.904 with no explicit bump. run 35513060618. (task 1002620)
2287
+ 1.19.906 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2288
+ landed since 1.19.905 with no explicit bump. run 35514202453. (task 1002620)
2287
2289
  ---------------------------------------------------------------------------
2288
2290
  ```
@@ -39,6 +39,11 @@
39
39
  }
40
40
  var fmtInt = function (n) { return OTB && OTB.fmtInt ? OTB.fmtInt(n) : String(n == null ? 0 : n); };
41
41
  var rankLabel = function (r) { return OTB && OTB.rankLabel ? OTB.rankLabel(r) : r; };
42
+ // A ROW TAG TAKES roleLabel() (dom-utils.js, task 1004041). Without it the Directory
43
+ // printed the column: lowercase 'engineer', 'ui' instead of 'UI', and — for a builder
44
+ // who has set no role — 'unclassified', which is the example V2 names, in the exact
45
+ // place it names it. Same defensive shape as rankLabel above: the pack may be absent.
46
+ var roleLabel = function (d) { return OTB && OTB.roleLabel ? OTB.roleLabel(d) : String(d); };
42
47
  var currencyLabel = function () {
43
48
  var b = window.OTBBranding;
44
49
  return (b && b.currencyLabel && b.currencyLabel({ caps: true })) || 'Credits';
@@ -70,7 +75,7 @@
70
75
  var list = Array.isArray(b.disciplines) ? b.disciplines : [];
71
76
  if (!list.length) return '<span class="dir-none">—</span>';
72
77
  return '<span class="dir-crafts">' + list.map(function (d) {
73
- return '<span class="fact-chip">' + esc(String(d)) + '</span>';
78
+ return '<span class="fact-chip">' + esc(roleLabel(d)) + '</span>';
74
79
  }).join('') + '</span>';
75
80
  }
76
81
 
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.905",
3
+ "version": "1.19.906",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.905",
9
+ "version": "1.19.906",
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.905",
3
+ "version": "1.19.906",
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.905'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.906'; // 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');
@@ -221,7 +221,12 @@ test('the directory row shows the avatar, the name and the login the API returns
221
221
  assert.match(src, /class="lb-name dir-name" href="https:\/\/github\.com\/' \+ encodeURIComponent\(b\.github_login\)/,
222
222
  'the shell\'s .lb-name, to the one page every listed builder has');
223
223
  assert.match(src, /'<span class="dir-login">@' \+ esc\(b\.github_login\)/, 'the login under the name says where the door goes');
224
- assert.match(src, /<span class="fact-chip">' \+ esc\(String\(d\)\)/, 'crafts are chips');
224
+ // The chip is the assertion; what goes IN it is the role vocabulary, not the column
225
+ // (task 1004040). This line used to pin `esc(String(d))` — the raw value — so it read as
226
+ // a guard on the chip while actually holding the Directory to rendering 'unclassified'
227
+ // and a lowercase 'ui'. Pinning the wrapper and the helper keeps the original intent
228
+ // without pinning the defect that happened to be inside it.
229
+ assert.match(src, /<span class="fact-chip">' \+ esc\(roleLabel\(d\)\)/, 'roles are chips, spoken not printed');
225
230
  assert.doesNotMatch(src, /class="num"/, 'the shell\'s ledger__num, not the bare .num scouting.js had corrected');
226
231
  assert.match(src, /class="ledger__num"/);
227
232
  });
@@ -58,6 +58,17 @@ function makeEl(id) {
58
58
  }
59
59
 
60
60
  // `count` builders, each distinct enough that a filter lens has something to bite.
61
+ // The REAL role vocabulary, for the same reason this file runs the real kit rather than a
62
+ // stub: a stub of roleLabel() would agree with a roleLabel() that was wrong. dom-utils.js
63
+ // is pure enough to run against two small objects (tests/collab_page.mjs does the same).
64
+ function realRoleLabel() {
65
+ const src = read('modules/hall-ui/public/dom-utils.js');
66
+ const win = { location: { search: '', hash: '', pathname: '/' }, addEventListener() {}, localStorage: null };
67
+ const doc = { addEventListener() {}, querySelector: () => null, querySelectorAll: () => [], documentElement: { dataset: {} } };
68
+ new Function('window', 'document', src)(win, doc);
69
+ return win.OTB.roleLabel;
70
+ }
71
+
61
72
  function buildersFor(count) {
62
73
  return Array.from({ length: count }, (_, i) => ({
63
74
  github_id: 1000 + i,
@@ -105,7 +116,6 @@ function harness({ count }) {
105
116
  // task 1003936 — the role axis vocabulary (dom-utils OTB.role*). PRESENT for
106
117
  // the same reason categoryChip is: an undefined helper throws mid-render.
107
118
  roleAxisLabel: () => 'Role',
108
- roleLabel: (d) => (!d ? '' : d === 'unclassified' ? 'No role yet' : d === 'ui' ? 'UI' : d.charAt(0).toUpperCase() + d.slice(1)),
109
119
  roleOptions: () => [{ value: '', label: '— any —' }, { value: 'engineer', label: 'Engineer' }, { value: 'artist', label: 'Artist' }],
110
120
  roleIsUnset: (d) => !d || d === 'unclassified',
111
121
  ROLE_UNSET: 'unclassified',
@@ -116,6 +126,13 @@ function harness({ count }) {
116
126
  fmtCompact: (n) => String(Number(n) || 0),
117
127
  fmtDate: (iso) => String(iso ?? '').slice(0, 10),
118
128
  rankLabel: (r) => String(r ?? ''),
129
+ // The REAL one, replacing a hand-written reimplementation that used to sit here.
130
+ // Two reasons it had to go, and the second is the point of this file: it was a
131
+ // duplicate object key once the real helper arrived (no-dupe-keys, the later
132
+ // definition silently winning), and a stub that restates roleLabel's own logic
133
+ // can drift from it and the test would never notice — which is the argument this
134
+ // file already makes for running the real kit.
135
+ roleLabel: realRoleLabel(),
119
136
  toast() {},
120
137
  },
121
138
  };
@@ -162,6 +179,32 @@ await test('the page asks for exactly the ceiling, and asks for it ONCE', async
162
179
  assert.equal(limit, CEILING, `the page must ask for the route ceiling (${CEILING})`);
163
180
  });
164
181
 
182
+ // --- task 1004040 (artist review of 1003936): the Directory speaks the role --------
183
+
184
+ await test('the role vocabulary a Directory chip renders through says the word, not the column', () => {
185
+ // The 1003936 grade named this as a nit — craftsHtml() rendering the raw discipline
186
+ // instead of routing it through roleLabel() — and a nit is advisory, so it survived two
187
+ // more rounds. What a reader saw: lowercase 'engineer', 'ui' where the house writes
188
+ // 'UI', and, for a builder who has set no role, the database's own 'unclassified' —
189
+ // the example V2 names, in the exact place it names it ("a filter option and a row tag").
190
+ //
191
+ // The BEHAVIOUR is executed: this is the shipped roleLabel, not a stub of it.
192
+ const roleLabel = realRoleLabel();
193
+ assert.equal(roleLabel('engineer'), 'Engineer');
194
+ assert.equal(roleLabel('ui'), 'UI', 'the acronym keeps its case');
195
+ assert.equal(roleLabel('unclassified'), 'No role yet', 'a sentence a person would say');
196
+
197
+ // The CALL SITE is read, because it cannot be executed here: the harness's document
198
+ // fake returns a fresh detached node from querySelector(), so the kit fills a <tbody>
199
+ // that never reaches the markup this file can see. Observing a rendered row would mean
200
+ // deepening that fake, which is a change to a shared harness and not an artist review's
201
+ // business. Named in the session log rather than left as a silent gap.
202
+ const src = read('modules/hall-ui/public/people.js');
203
+ assert.match(src, /esc\(roleLabel\(d\)\)/, 'the chip routes through the role vocabulary');
204
+ assert.doesNotMatch(src, /'<span class="fact-chip">' \+ esc\(String\(d\)\)/,
205
+ 'the raw column must not be rendered as a chip');
206
+ });
207
+
165
208
  await test('a SHORT directory is not hedged — the exact count is the honest one', async () => {
166
209
  const h = harness({ count: 3 });
167
210
  await tick(); await tick();