@bongos/core 1.19.117 → 1.19.118
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 +18 -13
- package/config/design-tokens.neutral.json +13 -13
- package/docs/design-contract.md +3 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +3 -1
- package/src/ui/adapters/claude-design/index.js +14 -2
- package/tests/design_tokens_sync.mjs +79 -0
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.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.118",
|
|
6
|
+
"core_contract": "1.19.118",
|
|
7
|
+
"source_commit": "b2c7044681ffb9b34e63677b0487f02dba2111df",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-14T19:32:31.077Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 302,
|
|
13
13
|
"agent_docs_stubbed": 21,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1239,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1562,
|
|
20
|
+
"tree_sha256": "d14e35ba8094c969d33de804077321c1dd6f7463d0d4a1d77585ebc85e501e7c",
|
|
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": "
|
|
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": "
|
|
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": "
|
|
4165
|
+
"sha256": "a21e300cabe4c1a3af1b84fcb4b190c8ee109acd79d888e04351cb9064162457"
|
|
4166
4166
|
},
|
|
4167
4167
|
{
|
|
4168
4168
|
"path": "package.json",
|
|
4169
4169
|
"mode": "0000644",
|
|
4170
|
-
"sha256": "
|
|
4170
|
+
"sha256": "4faa734f756086158c7c1d7983352c08d52961e479c1487aadba9a770007d19e"
|
|
4171
4171
|
},
|
|
4172
4172
|
{
|
|
4173
4173
|
"path": "public-docs/index.html",
|
|
@@ -5742,7 +5742,7 @@
|
|
|
5742
5742
|
{
|
|
5743
5743
|
"path": "src/module-api.js",
|
|
5744
5744
|
"mode": "0000644",
|
|
5745
|
-
"sha256": "
|
|
5745
|
+
"sha256": "2e899e310368c74a25215b99d3dabced0755c87f85569d23a069417dd20c661a"
|
|
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": "
|
|
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": "#
|
|
6
|
-
"bgCard": "#
|
|
7
|
-
"bgDeep": "#
|
|
8
|
-
"bgFrame": "#
|
|
9
|
-
"ink": "#
|
|
10
|
-
"inkSoft": "#
|
|
11
|
-
"inkFaint": "#
|
|
12
|
-
"rule": "#
|
|
13
|
-
"ruleSoft": "#
|
|
14
|
-
"accent": "#
|
|
15
|
-
"accentDeep": "#
|
|
16
|
-
"sea": "#
|
|
17
|
-
"terracotta": "#
|
|
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": {
|
package/docs/design-contract.md
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "1.19.118",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.118",
|
|
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.
|
|
3
|
+
"version": "1.19.118",
|
|
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
|
@@ -661,8 +661,10 @@ 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)
|
|
664
666
|
// ---------------------------------------------------------------------------
|
|
665
|
-
const CORE_VERSION = '1.19.
|
|
667
|
+
const CORE_VERSION = '1.19.118'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
666
668
|
|
|
667
669
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
668
670
|
// 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 ||
|
|
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) ||
|
|
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
|
+
});
|