@bongos/core 1.19.117 → 1.19.119

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.117",
6
- "core_contract": "1.19.117",
7
- "source_commit": "195266c548d657ee6924d36607d548a0e712cbf9",
5
+ "core_version": "1.19.119",
6
+ "core_contract": "1.19.119",
7
+ "source_commit": "1a3ff47e4556fdab934c24fb8e01bbb4bb01d095",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-14T18:51:25.372Z",
9
+ "built_at": "2026-08-14T20:02:21.430Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 302,
13
13
  "agent_docs_stubbed": 21,
14
- "functional_verbatim": 1238,
14
+ "functional_verbatim": 1239,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1561,
20
- "tree_sha256": "e8cb405106a8092556a788698759b8a579439a080653ec3d5a5db66d16ec8e6b",
19
+ "file_count": 1562,
20
+ "tree_sha256": "df9b1ed828fdacdb04089002baf65d5176be91c467884f599031bbd8218cae30",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -387,7 +387,7 @@
387
387
  {
388
388
  "path": "config/design-tokens.neutral.json",
389
389
  "mode": "0000644",
390
- "sha256": "16803a2b65d64052f9509b0ff50dbe36aadcc94639d5c6896736b1c9787a022b"
390
+ "sha256": "ffca38493475ebe55c6ac9513f8b7836162c26d2a532ef0a1cc6a3abc9ffac68"
391
391
  },
392
392
  {
393
393
  "path": "config/design-tokens.schema.json",
@@ -1367,7 +1367,7 @@
1367
1367
  {
1368
1368
  "path": "docs/design-contract.md",
1369
1369
  "mode": "0000644",
1370
- "sha256": "a86af6a923ed70bb8ea0846266f232f31a5fc9709d286362bcd37104d683342b"
1370
+ "sha256": "8a71b3573c3d9be7e543baa1817d42df81cd546e3cfd544c785533ccaa9da477"
1371
1371
  },
1372
1372
  {
1373
1373
  "path": "docs/design/front-door-and-hub-direction.md",
@@ -4162,12 +4162,12 @@
4162
4162
  {
4163
4163
  "path": "package-lock.json",
4164
4164
  "mode": "0000644",
4165
- "sha256": "2d570f38602e9cb4ab3417d45f21d61ffb2b9cef5ba9ff9354350a95af8f6190"
4165
+ "sha256": "2a008b4ca09e8abb2613478eb696fb66b63b4dd075cee7bbd6d7fb60a9866513"
4166
4166
  },
4167
4167
  {
4168
4168
  "path": "package.json",
4169
4169
  "mode": "0000644",
4170
- "sha256": "b9a96ae403012d889fbae5d2bd481f76fa1bc2221e5e8c8a6bd49e7494759ee9"
4170
+ "sha256": "ce8caad093e4acd61c3de150836996162c8265ed1ceb09a27130bbe58ea10aaf"
4171
4171
  },
4172
4172
  {
4173
4173
  "path": "public-docs/index.html",
@@ -4417,7 +4417,7 @@
4417
4417
  {
4418
4418
  "path": "public-landing/index.html",
4419
4419
  "mode": "0000644",
4420
- "sha256": "bddfd05afb8b2c93155efff9bfc6812a7e213ed7f4d66a8d4cd2db3c899d0088"
4420
+ "sha256": "1fa06d66fc4c1bbe3849e6fbf402852caea8b7cfc80a4c69ecad26d921d4264d"
4421
4421
  },
4422
4422
  {
4423
4423
  "path": "public-landing/projects.html",
@@ -5742,7 +5742,7 @@
5742
5742
  {
5743
5743
  "path": "src/module-api.js",
5744
5744
  "mode": "0000644",
5745
- "sha256": "1c1a8e95f442958ff1476c19e6b68fd2af5475e365e3d5203656bfb2c63f3fa4"
5745
+ "sha256": "a990b6b2c309018a149e0190b2fcd74a0d6e2b3754cfdd3eabdf505038a19d87"
5746
5746
  },
5747
5747
  {
5748
5748
  "path": "src/module-loader/catalog.js",
@@ -5787,7 +5787,7 @@
5787
5787
  {
5788
5788
  "path": "src/ui/adapters/claude-design/index.js",
5789
5789
  "mode": "0000644",
5790
- "sha256": "04218100d565edf00d822aefa262a001f503bf9f45ae79f4a46a3c2f1756ede5"
5790
+ "sha256": "7489ba1a6612068648359c65d1abeae8faa6de0d16e0cf58d67ce5a1f307e372"
5791
5791
  },
5792
5792
  {
5793
5793
  "path": "src/ui/adapters/figma/index.js",
@@ -6334,6 +6334,11 @@
6334
6334
  "mode": "0000644",
6335
6335
  "sha256": "1abfa6c8bb119d010d2a53f71373508a31a9cc3c28207ca1dbac2138a7eda595"
6336
6336
  },
6337
+ {
6338
+ "path": "tests/design_tokens_sync.mjs",
6339
+ "mode": "0000644",
6340
+ "sha256": "6d1a9dfba7e6ef7606c68abc9df3fb6e479f1a2939b83ad342f907b338f17f2c"
6341
+ },
6337
6342
  {
6338
6343
  "path": "tests/dev_lib.mjs",
6339
6344
  "mode": "0000644",
@@ -2,19 +2,19 @@
2
2
  "_note": "Cloud Bongos neutral design tokens — the baseline every instance resolves over. To override, copy values into config/design-tokens.json (the instance pack). These match config/branding.neutral.json theme.ui so a vanilla instance with no instance pack still renders correctly. See docs/design-contract.md.",
3
3
 
4
4
  "colors": {
5
- "bg": "#fff7ed",
6
- "bgCard": "#ffffff",
7
- "bgDeep": "#ffedd5",
8
- "bgFrame": "#fde4c8",
9
- "ink": "#2a1f17",
10
- "inkSoft": "#6b5d52",
11
- "inkFaint": "#857567",
12
- "rule": "#fdba74",
13
- "ruleSoft": "#fed7aa",
14
- "accent": "#f97316",
15
- "accentDeep": "#ea580c",
16
- "sea": "#38bdf8",
17
- "terracotta": "#fb7185"
5
+ "bg": "#f9d9a8",
6
+ "bgCard": "#fffaf2",
7
+ "bgDeep": "#f6d8ae",
8
+ "bgFrame": "#f0c489",
9
+ "ink": "#2b170e",
10
+ "inkSoft": "#6d4a33",
11
+ "inkFaint": "#785a41",
12
+ "rule": "#e8a463",
13
+ "ruleSoft": "#f6d8ae",
14
+ "accent": "#ce4806",
15
+ "accentDeep": "#9e3406",
16
+ "sea": "#0f7a96",
17
+ "terracotta": "#855b3d"
18
18
  },
19
19
 
20
20
  "fonts": {
@@ -30,7 +30,7 @@ The validator merges both files (deep-merge, instance wins) and validates the re
30
30
 
31
31
  ### 1.3 Relationship to config/branding.json
32
32
 
33
- `config/branding.json` carries *identity* (product name, domains, currency, tracks). Design tokens carry *presentation* (colors, type, spacing). The two files are siblings; neither owns the other. Where both define overlapping values (e.g. `branding.json theme.ui.colors` and `design-tokens.json colors`), **design-tokens.json is authoritative at render time**. The `src/branding.js` resolver will be updated (task 1377) to expose resolved tokens alongside identity — adapters use `branding.resolveDesignTokens()`.
33
+ `config/branding.json` carries *identity* (product name, domains, currency, tracks). Design tokens carry *presentation* (colors, type, spacing). The two files are siblings; neither owns the other. Where both define overlapping values (e.g. `branding.json theme.ui.colors` and `design-tokens.json colors`), **design-tokens.json is authoritative at render time**. The **neutral pair** is the one exception: `config/branding.neutral.json theme.ui` is the authority and `config/design-tokens.neutral.json` mirrors it key-for-key — CI-asserted by `tests/design_tokens_sync.mjs` (task 1002752), so the design round-trip can never again start prototypes from colours the product stopped painting. Instance packs stay free per §1.2. The `src/branding.js` resolver will be updated (task 1377) to expose resolved tokens alongside identity — adapters use `branding.resolveDesignTokens()`.
34
34
 
35
35
  ### 1.4 Token schema overview
36
36
 
@@ -290,6 +290,8 @@ The `--dt-` prefix is reserved for this design system. Adapters must not emit CS
290
290
  6. Every `surfaceId` key in `design-sources.json` has a matching directory under `src/ui/` or `assets/ui/` (if any such directory exists — the file may precede the directories for a new instance).
291
291
  7. If `src/ui/adapters/` exists, each adapter directory has an `index.js` that exports `id`, `import`, and `export`.
292
292
 
293
+ The neutral-pair lockstep (§1.3) is deliberately not a validator check — it lives in `tests/design_tokens_sync.mjs`, so an instance running only `validate-design.js` is not forced to mirror its own pack.
294
+
293
295
  Usage:
294
296
 
295
297
  ```
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.117",
3
+ "version": "1.19.119",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.117",
9
+ "version": "1.19.119",
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.117",
3
+ "version": "1.19.119",
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",
@@ -79,11 +79,15 @@ h1.big{font-family:var(--font-display);font-weight:700;font-size:clamp(33px,5.4v
79
79
  The head is SKIN, not a card. It carries its own --skin-* tokens and must
80
80
  NEVER inherit --bg-card — that turns it black in dark mode. These are
81
81
  component-scoped (on .bongos, not :root) so they cannot collide with the
82
- pack's contract tier. */
82
+ pack's contract tier.
83
+
84
+ The ground shadow follows cosmos.css's --shadow-card rule: ink-derived in
85
+ light (warm brown), plain black in dark — in dark, --ink is near-white and
86
+ an ink fill would glow, not shade. */
83
87
  .bongos{display:block;width:100%;height:auto;overflow:visible;
84
- --skin-hi:#fffdf8;--skin-mid:#fff6e9;--skin-lo:#e8d3b6;}
85
- :root[data-mode="dark"] .bongos{--skin-hi:#fdf7ea;--skin-mid:#efe1c8;--skin-lo:#c3ae90;}
86
- @media (prefers-color-scheme:dark){:root:not([data-mode="light"]) .bongos{--skin-hi:#fdf7ea;--skin-mid:#efe1c8;--skin-lo:#c3ae90;}}
88
+ --skin-hi:#fffdf8;--skin-mid:#fff6e9;--skin-lo:#e8d3b6;--drum-shadow:var(--ink);}
89
+ :root[data-mode="dark"] .bongos{--skin-hi:#fdf7ea;--skin-mid:#efe1c8;--skin-lo:#c3ae90;--drum-shadow:#000;}
90
+ @media (prefers-color-scheme:dark){:root:not([data-mode="light"]) .bongos{--skin-hi:#fdf7ea;--skin-mid:#efe1c8;--skin-lo:#c3ae90;--drum-shadow:#000;}}
87
91
  .mascot{position:relative;}
88
92
  .mascot::before{content:"";position:absolute;inset:-8% -12%;z-index:-1;border-radius:50%;
89
93
  background:radial-gradient(ellipse at center,rgba(255,255,255,.95) 0%,rgba(255,255,255,.7) 45%,rgba(255,255,255,0) 72%);}
@@ -274,7 +278,7 @@ h1.big{font-family:var(--font-display);font-weight:700;font-size:clamp(33px,5.4v
274
278
 
275
279
  <ellipse class="glow" cx="222" cy="170" rx="215" ry="140" fill="url(#halo)"/>
276
280
  <ellipse class="bshadow" cx="220" cy="286" rx="142" ry="14"
277
- fill="var(--ink)" opacity=".22" filter="url(#soft)"/>
281
+ fill="var(--drum-shadow)" opacity=".22" filter="url(#soft)"/>
278
282
 
279
283
  <!-- the joining block, behind both shells -->
280
284
  <path d="M 214,196 C 232,188 250,188 264,196 L 258,232 C 244,225 230,225 219,232 Z" fill="var(--accent-deep)"/>
package/src/module-api.js CHANGED
@@ -661,8 +661,12 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
661
661
  // landed since 1.19.115 with no explicit bump. run 31827642395. (task 1002620)
662
662
  // 1.19.117 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
663
663
  // landed since 1.19.116 with no explicit bump. run 31830559253. (task 1002620)
664
+ // 1.19.118 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
665
+ // landed since 1.19.117 with no explicit bump. run 31833658900. (task 1002620)
666
+ // 1.19.119 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
667
+ // landed since 1.19.118 with no explicit bump. run 31835957309. (task 1002620)
664
668
  // ---------------------------------------------------------------------------
665
- const CORE_VERSION = '1.19.117'; // CI auto-patch carrier (ADR 0161); see changelog above
669
+ const CORE_VERSION = '1.19.119'; // CI auto-patch carrier (ADR 0161); see changelog above
666
670
 
667
671
  // A namespaced logger so a module's log lines are attributable + consistent.
668
672
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -20,6 +20,18 @@ const os = require('node:os');
20
20
 
21
21
  const ID = 'claude-design';
22
22
 
23
+ // Fallback when a caller-supplied token tree omits colors.accent — resolved from
24
+ // the neutral token file so the adapter never carries a brand literal of its own;
25
+ // the catch value is the neutral pack's accent, kept equal by
26
+ // tests/design_tokens_sync.mjs (task 1002752).
27
+ const FALLBACK_ACCENT = (() => {
28
+ try {
29
+ return JSON.parse(fs.readFileSync(
30
+ path.resolve(__dirname, '..', '..', '..', '..', 'config', 'design-tokens.neutral.json'), 'utf8',
31
+ )).colors.accent || '#ce4806';
32
+ } catch { return '#ce4806'; }
33
+ })();
34
+
23
35
  // ── token helpers ─────────────────────────────────────────────────────────────
24
36
 
25
37
  function camelToKebab(s) {
@@ -159,7 +171,7 @@ label{display:block;font-size:10px;color:#888;text-transform:uppercase;letter-sp
159
171
  function spacingHtml(tokens) {
160
172
  const scale = tokens.scale || {};
161
173
  const colors = tokens.colors || {};
162
- const accent = colors.accent || '#f97316';
174
+ const accent = colors.accent || FALLBACK_ACCENT;
163
175
  const rows = Object.entries(scale).map(([k, v]) => `
164
176
  <tr>
165
177
  <td><code>${k}</code></td>
@@ -182,7 +194,7 @@ code{font-size:12px;}
182
194
 
183
195
  function radiiHtml(tokens) {
184
196
  const radius = tokens.radius || {};
185
- const accent = (tokens.colors && tokens.colors.accent) || '#f97316';
197
+ const accent = (tokens.colors && tokens.colors.accent) || FALLBACK_ACCENT;
186
198
  const boxes = Object.entries(radius).map(([k, v]) => `
187
199
  <div style="display:inline-block;margin:8px;">
188
200
  <div style="width:64px;height:64px;background:${accent};border-radius:${v};"></div>
@@ -0,0 +1,79 @@
1
+ // tests/design_tokens_sync.mjs — config/design-tokens.neutral.json mirrors the
2
+ // branding pack, never a palette of its own (task 1002752).
3
+ //
4
+ // The repo has two files describing the neutral look: config/branding.neutral.json
5
+ // (the RUNTIME pack — themeMarkup() paints every served page with it) and
6
+ // config/design-tokens.neutral.json (the DESIGN-side tokens feeding the Figma /
7
+ // Claude Design round-trip). Nothing tied them together, so the design file kept
8
+ // the pre-1002749 palette — including the exact accents removed for failing WCAG
9
+ // AA — and every prototype started from colours the product no longer paints.
10
+ // Model: the fallback-equals-pack assertions in tests/devbox_dmg_backdrop.mjs.
11
+ //
12
+ // Run: node tests/design_tokens_sync.mjs
13
+
14
+ import { strict as assert } from 'node:assert';
15
+ import { test } from 'node:test';
16
+ import fs from 'node:fs';
17
+ import path from 'node:path';
18
+ import { fileURLToPath } from 'node:url';
19
+
20
+ const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
21
+ const readJson = (...p) => JSON.parse(fs.readFileSync(path.join(REPO_ROOT, ...p), 'utf8'));
22
+
23
+ const pack = readJson('config', 'branding.neutral.json');
24
+ const tokens = readJson('config', 'design-tokens.neutral.json');
25
+
26
+ // Strip comments so rationale prose — which must be free to name a removed
27
+ // colour — never trips a scan of the CODE (the stripCommentsForIdentity
28
+ // contract, as applied in tests/devbox_dmg_backdrop.mjs).
29
+ function codeOnly(text) {
30
+ return text
31
+ .replace(/\/\*[\s\S]*?\*\//g, '')
32
+ .split(/\r?\n/)
33
+ .map((line) => line.replace(/(^|[^:"'])\/\/.*$/, '$1'))
34
+ .join('\n');
35
+ }
36
+
37
+ test('every design-token colour is the branding pack value — a divergent token is a fork of the brand', () => {
38
+ const packColors = pack.theme.ui.colors;
39
+ assert.deepEqual(
40
+ Object.keys(tokens.colors || {}).sort(), Object.keys(packColors).sort(),
41
+ 'the design file must carry exactly the pack colour keys — a missing or extra key is drift too, ' +
42
+ 'running through the key set instead of the values');
43
+ for (const [key, val] of Object.entries(tokens.colors)) {
44
+ assert.equal(String(val).toLowerCase(), String(packColors[key]).toLowerCase(),
45
+ `design-token "${key}" must equal the pack's value — a drifted token hands every prototype ` +
46
+ 'a palette the product no longer paints');
47
+ }
48
+ });
49
+
50
+ test('the fonts the two files share are the same fonts', () => {
51
+ const packFonts = pack.theme.ui.fonts;
52
+ for (const [key, val] of Object.entries(tokens.fonts || {})) {
53
+ if (!(key in packFonts)) continue; // mono is design-side only — the pack declares no mono surface
54
+ assert.deepEqual(val, packFonts[key],
55
+ `design-token font "${key}" must equal the pack's — same drift class as the colours`);
56
+ }
57
+ });
58
+
59
+ test('the claude-design adapter falls back to the pack accent, never a brand literal of its own', () => {
60
+ const source = fs.readFileSync(
61
+ path.join(REPO_ROOT, 'src', 'ui', 'adapters', 'claude-design', 'index.js'), 'utf8');
62
+ const block = source.match(/const FALLBACK_ACCENT =[\s\S]*?\}\)\(\);/);
63
+ assert.ok(block, 'the adapter declares one resolved fallback accent instead of inline literals');
64
+ assert.match(block[0], /design-tokens\.neutral\.json/,
65
+ 'the fallback resolves from the neutral token file, never a bare literal');
66
+ for (const hex of block[0].match(/#[0-9a-fA-F]{6}\b/g) || []) {
67
+ assert.equal(hex.toLowerCase(), String(pack.theme.ui.colors.accent).toLowerCase(),
68
+ 'the catch literal must be the pack ACCENT, not merely some pack colour');
69
+ }
70
+ // Every colour literal left in the adapter must be the neutral pack's own value
71
+ // (i.e. a fallback, not a brand). The preview-card chrome is 3-digit grays, so
72
+ // a 6-digit literal is exactly the brand-value class.
73
+ const packValues = new Set(Object.values(pack.theme.ui.colors).map((h) => String(h).toLowerCase()));
74
+ const hexes = codeOnly(source).match(/#[0-9a-fA-F]{6}\b/g) || [];
75
+ for (const hex of hexes) {
76
+ assert.ok(packValues.has(hex.toLowerCase()),
77
+ `hardcoded colour ${hex} in the claude-design adapter — resolve it from the tokens instead`);
78
+ }
79
+ });