@bongos/core 1.19.521 → 1.19.523

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.521",
6
- "core_contract": "1.19.521",
7
- "source_commit": "e4f2e1b87d89acb6c50a86896af501eff629a49f",
5
+ "core_version": "1.19.523",
6
+ "core_contract": "1.19.523",
7
+ "source_commit": "4d6bf53e6443bf737775e277080d2f14f574edad",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-03T22:32:55.137Z",
9
+ "built_at": "2026-09-03T23:12:58.339Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 431,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 2424,
20
- "tree_sha256": "5cf629aad21665a1b205bb6529f9103bde6140bdaa5d5bb8bb950677b588c058",
20
+ "tree_sha256": "baf1d9a541cc968505997bdc199995e36491ed289791585d1d3dcf1bb66ff004",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -2597,7 +2597,7 @@
2597
2597
  {
2598
2598
  "path": "docs/module-api-changelog.md",
2599
2599
  "mode": "0000644",
2600
- "sha256": "f19fae1616ebe6fcb885f54592364bc673ed8df8ac23c857377c7959490c87b6"
2600
+ "sha256": "595be3b748b8664a50fcde28667fbe25e1cf43894753499e9f7b0bbf30518e89"
2601
2601
  },
2602
2602
  {
2603
2603
  "path": "docs/modules-contract.md",
@@ -4942,7 +4942,7 @@
4942
4942
  {
4943
4943
  "path": "modules/hall-ui/public/profile.css",
4944
4944
  "mode": "0000644",
4945
- "sha256": "2d3b4596ce8cbafcaef71d2882351c764a030bdbfeee51192136ec7f17c86475"
4945
+ "sha256": "1243e933c4ff11e491bac6f1791f269cc80722d6bdceeae7e5dbc1dda5c91324"
4946
4946
  },
4947
4947
  {
4948
4948
  "path": "modules/hall-ui/public/profile.html",
@@ -4957,7 +4957,7 @@
4957
4957
  {
4958
4958
  "path": "modules/hall-ui/public/profile.states.json",
4959
4959
  "mode": "0000644",
4960
- "sha256": "d981e8d2b50d04d4b0e5cfecd051d2a5b77d7aeac532c712a3b5d269defbd3ce"
4960
+ "sha256": "3df74097937e52577f25255a4612b7be93effc491bc32f2f6bc81ddb91b28929"
4961
4961
  },
4962
4962
  {
4963
4963
  "path": "modules/hall-ui/public/ranks.html",
@@ -5077,7 +5077,7 @@
5077
5077
  {
5078
5078
  "path": "modules/hall-ui/public/style.css",
5079
5079
  "mode": "0000644",
5080
- "sha256": "41aae0ec3164d3f0e4d485ad029c98980b2d18e791a04aa4e7714ba94e776ef9"
5080
+ "sha256": "f3d877972513fa23f2819a91f34c4901ca5e692faad6dcf096377a6b1d5b1be4"
5081
5081
  },
5082
5082
  {
5083
5083
  "path": "modules/hall-ui/public/task-detail.js",
@@ -5152,7 +5152,7 @@
5152
5152
  {
5153
5153
  "path": "modules/hall-ui/public/work.states.json",
5154
5154
  "mode": "0000644",
5155
- "sha256": "c6356fe3a0640cddbe49ee2d91b30d6dece74ca58105067f1384d1e7d0718117"
5155
+ "sha256": "929512f085f138f93170f643dbd68615dfbf6d5fcd5f0bf1abf30a081154b536"
5156
5156
  },
5157
5157
  {
5158
5158
  "path": "modules/ideas/CLAUDE.md",
@@ -7297,12 +7297,12 @@
7297
7297
  {
7298
7298
  "path": "package-lock.json",
7299
7299
  "mode": "0000644",
7300
- "sha256": "b18f028ece28c2fd6605db03201f068504d5b57a2a402d79f2f28bad551e2ddc"
7300
+ "sha256": "36fb0fa1abd3d8ec9b1bee4457ec3a8541e1b753aaaf9fcf93780ac65e3efc9a"
7301
7301
  },
7302
7302
  {
7303
7303
  "path": "package.json",
7304
7304
  "mode": "0000644",
7305
- "sha256": "d6b8d673c517a74dc369500ba850c49d367d860455f97c3a265525c5588057a4"
7305
+ "sha256": "51c3aef45b0e71569102672d27df52abaff4814663a45da0731ac8b3e9557e0e"
7306
7306
  },
7307
7307
  {
7308
7308
  "path": "public-docs/index.html",
@@ -8972,7 +8972,7 @@
8972
8972
  {
8973
8973
  "path": "src/module-api.js",
8974
8974
  "mode": "0000644",
8975
- "sha256": "192a36ccb6a9fb1b60332dda5c8ad12c5b53d104d9f9554d72505645ed66d7d3"
8975
+ "sha256": "aaf11ce9202e128bdcdd317e26a27a2d1f1ff1a7f73d6d996dc0a79f879ad3b6"
8976
8976
  },
8977
8977
  {
8978
8978
  "path": "src/module-loader/catalog.js",
@@ -10362,7 +10362,7 @@
10362
10362
  {
10363
10363
  "path": "tests/hall_board_world.mjs",
10364
10364
  "mode": "0000644",
10365
- "sha256": "b0ef3e407d7bd9266231dc089f1288ee40efb113e40333f79d3de4436db6cc21"
10365
+ "sha256": "196742bcff58511c21c891011a48448ef95a292bd84dc164d3fccb2620de838a"
10366
10366
  },
10367
10367
  {
10368
10368
  "path": "tests/hall_catalog_world.mjs",
@@ -10412,7 +10412,7 @@
10412
10412
  {
10413
10413
  "path": "tests/hall_profile_world.mjs",
10414
10414
  "mode": "0000644",
10415
- "sha256": "b35d647c4cb7b90be70dee8e7245396cc901479992fafbf19ceef734d8195399"
10415
+ "sha256": "d35886df220d7726011bc0d61ae85a273a4e9f9ee14c5d10f0a0753f4cfee4eb"
10416
10416
  },
10417
10417
  {
10418
10418
  "path": "tests/hall_reading_world.mjs",
@@ -1479,5 +1479,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
1479
1479
  landed since 1.19.519 with no explicit bump. run 33810716476. (task 1002620)
1480
1480
  1.19.521 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1481
1481
  landed since 1.19.520 with no explicit bump. run 33813285951. (task 1002620)
1482
+ 1.19.522 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1483
+ landed since 1.19.521 with no explicit bump. run 33815020928. (task 1002620)
1484
+ 1.19.523 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1485
+ landed since 1.19.522 with no explicit bump. run 33816191865. (task 1002620)
1482
1486
  ---------------------------------------------------------------------------
1483
1487
  ```
@@ -70,7 +70,12 @@
70
70
  #activity-scroll .ledger td a,
71
71
  #charts-scroll a,
72
72
  #works-scroll .scroll__lede a,
73
- #xp-scroll a {
73
+ #xp-scroll a,
74
+ /* The signed-out empty state (renderEmpty) — two links inside a prose
75
+ sentence. --fixture-me always answers /me, so this markup never
76
+ rendered in the re-skin's passes and its links stayed 18px (walk
77
+ 1003309). Joining the list keeps ONE recipe, not a second copy. */
78
+ #profile-head .profile__placeholder a {
74
79
  display: inline-block;
75
80
  min-width: 24px;
76
81
  min-height: 24px;
@@ -89,6 +89,7 @@
89
89
  }
90
90
  },
91
91
  "out": {
92
+ "_": "A signed-out visitor with no ?id= gets renderEmpty(), not a bounce — but this state only RENDERS that empty markup against the kit's own stub. Run it WITHOUT --base-out: under the hall-preview harness's --fixture-me the /me read still answers, so `out` quietly renders the viewer's own populated profile and the empty state is never measured. That is how its two prose links sat at 18px, under the 24px control floor, through the whole re-skin (walk 1003309, fixed in task 1003497).",
92
93
  "auth": false,
93
94
  "actions": [
94
95
  [
@@ -1526,6 +1526,12 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1526
1526
  display: flex;
1527
1527
  flex-direction: column;
1528
1528
  gap: 4px;
1529
+ /* A flex item defaults to min-width:auto, i.e. it will not shrink below its
1530
+ content — and a <select> sizes to its widest OPTION. At 320 that made the
1531
+ goal filter 331px and pushed the whole PAGE sideways, since this row has
1532
+ no scroller of its own the way .kit-tabs does (task 1003498). */
1533
+ min-width: 0;
1534
+ max-width: 100%;
1529
1535
  font-family: var(--label-face);
1530
1536
  font-size: var(--label-size);
1531
1537
  letter-spacing: var(--label-space);
@@ -1533,7 +1539,12 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1533
1539
  color: var(--ink-faint);
1534
1540
  }
1535
1541
  .filter select {
1536
- min-width: 150px;
1542
+ /* The floor keeps the controls in a filter bar a uniform width — but a
1543
+ bare 150px would itself refuse to shrink in a cell narrower than that,
1544
+ which is the very failure this task is about. min() keeps the floor
1545
+ wherever there is room and drops it where there is not. */
1546
+ min-width: min(150px, 100%);
1547
+ max-width: 100%;
1537
1548
  min-height: 32px;
1538
1549
  font-family: var(--font-body);
1539
1550
  padding: 4px 8px;
@@ -1545,7 +1556,8 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1545
1556
  /* task 1829: the Work Board free-text search box, sized to match the filter
1546
1557
  selects it sits alongside. */
1547
1558
  .filter input[type="search"] {
1548
- min-width: 200px;
1559
+ min-width: min(200px, 100%);
1560
+ max-width: 100%;
1549
1561
  min-height: 32px;
1550
1562
  font-family: var(--font-body);
1551
1563
  padding: 4px 8px;
@@ -12,7 +12,7 @@
12
12
  "in-progress": { "auth": true, "url": "/builders/work#in-progress", "actions": [["wait", 400]], "expect": { "visible": ["#wip-scroll"] } },
13
13
  "backlog": { "auth": true, "url": "/builders/work#backlog", "actions": [["wait", 400]], "expect": { "visible": ["#backlog-scroll"] } },
14
14
  "completed": { "auth": true, "url": "/builders/work#completed", "actions": [["wait", 400]], "expect": { "visible": ["#history-scroll"] } },
15
- "filters-open": { "auth": true, "actions": [["clickIfVisible", "#work-filters [aria-expanded=\"false\"]"], ["wait", 250]] },
15
+ "filters-open": { "_": "The drawer open — the state that catches a filter CONTROL refusing to shrink. A <select> sizes to its widest OPTION and .filter is a flex item, so at 320 the goal filter stood at 331px and pushed the whole PAGE sideways (scrollWidth 358) instead of scrolling in a row of its own the way .kit-tabs does. 320 is the width that shows it — 1440 and 390 stay clean either way (walk 1003309, fixed in task 1003498).", "auth": true, "actions": [["clickIfVisible", "#work-filters [aria-expanded=\"false\"]"], ["wait", 250]] },
16
16
  "out": { "auth": false }
17
17
  },
18
18
  "reducedMotion": { "auth": true }
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.521",
3
+ "version": "1.19.523",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.521",
9
+ "version": "1.19.523",
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.521",
3
+ "version": "1.19.523",
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
@@ -45,7 +45,7 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
45
45
  // there. scripts/gds/bump-version.js still rewrites the literal below; it appends
46
46
  // the entry to that file. Look for a version's history there, not here.
47
47
  // ---------------------------------------------------------------------------
48
- const CORE_VERSION = '1.19.521'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
48
+ const CORE_VERSION = '1.19.523'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
49
49
 
50
50
  // A namespaced logger so a module's log lines are attributable + consistent.
51
51
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -429,3 +429,47 @@ test('RUN: the three notices are inbox lines with a kind, a line and — where o
429
429
  covered.api.renderProfile(ME.builder);
430
430
  assert.equal(covered.el('attention-system').innerHTML, '', 'a covered need is not an action');
431
431
  });
432
+
433
+ // ---- 9. the filter drawer fits the narrowest phone (task 1003498) -----------
434
+
435
+ // At 320 the goal select sized itself to its widest OPTION ("BONGOS-V1 —
436
+ // general …") at 331px, and `.filter` — a flex item at the default
437
+ // min-width:auto — could not shrink under it. Both sat with their right edge at
438
+ // 357 inside a visible-overflow parent, so they pushed the PAGE sideways rather
439
+ // than scrolling in a row of their own (walk 1003309). The status tab strip
440
+ // overflows too, but its row is overflow-x:auto and scrolls itself, which is
441
+ // why the fix belongs on the control and not on the drawer.
442
+ const ruleFor = (css, selector) => {
443
+ const re = new RegExp(`(?:^|\\r?\\n)${selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*\\{([^}]*)\\}`);
444
+ const m = re.exec(css);
445
+ assert.ok(m, `${selector} rule present in style.css`);
446
+ return m[1];
447
+ };
448
+
449
+ test('a filter control may shrink below its content, so the drawer never pushes the page', () => {
450
+ const filter = ruleFor(styleCss, '.filter');
451
+ assert.match(filter, /min-width:\s*0\b/, '.filter is a flex item: min-width:auto is what pinned it to its content');
452
+ assert.match(filter, /max-width:\s*100%/, 'and it may not exceed the row it sits in');
453
+
454
+ // The select is the thing with the runaway intrinsic width. It keeps its
455
+ // 150px floor for wide screens — a filter narrower than that is unreadable —
456
+ // and gains a cap so a long option label cannot widen it past its cell.
457
+ const select = ruleFor(styleCss, '.filter select');
458
+ assert.match(select, /max-width:\s*100%/, 'the select is capped to its cell');
459
+ // The floor is expressed so it CANNOT itself pin the control: a bare 150px
460
+ // would refuse to shrink in a cell narrower than 150px, which is the same
461
+ // failure this task fixed one level up (grader nit, task 1003498).
462
+ assert.match(select, /min-width:\s*min\(150px,\s*100%\)/, 'the floor holds where there is room and drops where there is not');
463
+
464
+ // The free-text search box sits in the same wrapping row and would do the
465
+ // same thing at 320 with its 200px floor.
466
+ assert.match(ruleFor(styleCss, '.filter input[type="search"]'), /max-width:\s*100%/,
467
+ 'the search box is capped the same way');
468
+ });
469
+
470
+ test('the tab strip is left alone — it scrolls in its own row and never moved the page', () => {
471
+ // Named so a later reader does not "fix" the wider element and miss the cause.
472
+ const strip = /\.setup__tabs\s*\{([^}]*)\}/.exec(styleCss) || /\.kit-tabs\s*\{([^}]*)\}/.exec(styleCss);
473
+ assert.ok(strip, 'the tab strip rule is present');
474
+ assert.match(strip[1], /overflow-x:\s*auto/, 'it scrolls itself, which is why it is not the overflow cause');
475
+ });
@@ -456,3 +456,41 @@ test('the profile states file renders each rail key, so the floors cover every s
456
456
  assert.equal(states.states.activity.url, '/profile#activity');
457
457
  assert.ok(states.states.activity.expect.visible.includes('#activity-tabs'));
458
458
  });
459
+
460
+ // ---- the signed-out empty state (task 1003497) -------------------------------
461
+
462
+ // renderEmpty() is what a visitor with NO session and no ?id= sees. The
463
+ // hall-preview harness always answers /me, so under --fixture-me the `out`
464
+ // state renders the viewer's own profile and this markup never appeared in the
465
+ // re-skin's own passes — its two prose links were 18px tall on every render
466
+ // until the walk (task 1003309) put the state through the kit's own stub.
467
+ test('the signed-out empty state carries two prose links, and they take the 24px recipe', () => {
468
+ const empty = /function renderEmpty\(\)[\s\S]*?\n \}/.exec(profileJs);
469
+ assert.ok(empty, 'renderEmpty() present');
470
+ assert.match(empty[0], /class="profile__placeholder"/, 'the empty state is the placeholder block');
471
+ const links = empty[0].match(/<a\s[^>]*href=/g) || [];
472
+ assert.equal(links.length, 2, 'two prose links: the roster, and sign in');
473
+
474
+ // The recipe is ONE rule, shared. The empty state must join that selector
475
+ // list rather than grow a second copy of the same five declarations.
476
+ const recipe = /#works-scroll \.ledger td a,[\s\S]*?\{([^}]*)\}/.exec(profileCss);
477
+ assert.ok(recipe, 'the prose-link recipe block is findable');
478
+ assert.match(recipe[0], /#profile-head \.profile__placeholder a\b/,
479
+ 'the empty state\'s links are IN the shared recipe, not a separate rule');
480
+ assert.match(recipe[1], /min-height:\s*24px/, 'the recipe buys the height');
481
+ assert.match(recipe[1], /min-width:\s*24px/, 'and the width');
482
+ assert.match(recipe[1], /display:\s*inline-block/, 'which an inline anchor cannot take without this');
483
+ });
484
+
485
+ test('the out state says out loud that it only renders empty against the kit stub', () => {
486
+ const states = JSON.parse(read('profile.states.json'));
487
+ const out = states.states.out;
488
+ assert.equal(out.auth, false, 'out is the signed-out state');
489
+ // The file-level `_` said this in its last clause and it was still missed —
490
+ // which is how the state went unmeasured. The warning belongs ON the state a
491
+ // reader is about to run.
492
+ assert.ok(out._ && /stub/i.test(out._),
493
+ 'the out state carries its own note naming the kit stub as the only way it renders empty');
494
+ assert.ok(/fixture-me/.test(out._),
495
+ 'and names --fixture-me as the thing that hides the empty state');
496
+ });