synthesisui 0.16.35 → 0.16.36

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.
@@ -5,9 +5,32 @@ import { diagnose, scanSource } from "../doctor/scan.js";
5
5
  import { buildTable } from "../doctor/tokens.js";
6
6
  import { body, paint, section } from "../output.js";
7
7
  import { walk, walkAll } from "./doctor.js";
8
- /** How many distinct values travel. A census is a vocabulary, not a log: past
9
- * the first few dozen repeats the tail is noise nobody will name. */
10
- const MAX_VALUES = 120;
8
+ /**
9
+ * How many distinct values travel, PER KIND.
10
+ *
11
+ * It was one global cap of 120, and a real app broke it (30/07): 2876 files,
12
+ * 3976 findings, and the payload came back holding exactly 120 - ranked by
13
+ * frequency with every kind competing for the same slots. Two things went wrong
14
+ * there, and the second is the serious one:
15
+ *
16
+ * - radius and spacing lost their slots to colour, so the scale downstream
17
+ * would have been built from a partial set
18
+ * - the NEAR-DUPLICATE colours - a fifth grey used three times, the twin of
19
+ * the brand blue - are by definition low-frequency, which is exactly what a
20
+ * frequency-ranked cut throws away first. The collapse that justifies the
21
+ * whole v2 lives in that tail.
22
+ *
23
+ * So colour gets a deep budget and the dimensional families get their own. The
24
+ * worst case is ~380 entries, about 30KB of json - cheap for the one payload
25
+ * that describes somebody's entire vocabulary.
26
+ */
27
+ const MAX_PER_KIND = {
28
+ color: 250,
29
+ radius: 60,
30
+ spacing: 60,
31
+ motion: 40,
32
+ font: 30,
33
+ };
11
34
  /**
12
35
  * Dependencies as the project actually resolves them - which means reading
13
36
  * ANCESTOR package.json files too.
@@ -111,16 +134,34 @@ function distinctValues(d) {
111
134
  token: f.token,
112
135
  });
113
136
  }
114
- return [...by.values()]
115
- .sort((a, b) => b.count - a.count || a.value.localeCompare(b.value))
116
- .slice(0, MAX_VALUES)
117
- .map((v) => ({
118
- kind: v.kind,
119
- value: v.value,
120
- count: v.count,
121
- files: v.files.size,
122
- token: v.token,
123
- }));
137
+ // Per-kind budgets, each family ranked inside its own: colour never starves
138
+ // radius, and the low-frequency tail of colour (where near-duplicates live)
139
+ // survives a cut that a global cap would have made first.
140
+ const kept = [];
141
+ const dropped = new Map();
142
+ for (const kind of Object.keys(MAX_PER_KIND)) {
143
+ const family = [...by.values()]
144
+ .filter((v) => v.kind === kind)
145
+ .sort((a, b) => b.count - a.count || a.value.localeCompare(b.value));
146
+ const budget = MAX_PER_KIND[kind];
147
+ if (family.length > budget)
148
+ dropped.set(kind, family.length - budget);
149
+ for (const v of family.slice(0, budget)) {
150
+ kept.push({
151
+ kind: v.kind,
152
+ value: v.value,
153
+ count: v.count,
154
+ files: v.files.size,
155
+ token: v.token,
156
+ });
157
+ }
158
+ }
159
+ // NO SILENT CAPS: a payload that quietly stops at a budget reads as "this is
160
+ // everything you have", which is the one thing a census must never imply.
161
+ for (const [kind, n] of dropped) {
162
+ console.log(body(paint.faint(`(${n} more ${kind} value${n === 1 ? "" : "s"} exist below the ${MAX_PER_KIND[kind]} we carry - each used less often than the ones above)`)));
163
+ }
164
+ return kept.sort((a, b) => b.count - a.count || a.value.localeCompare(b.value));
124
165
  }
125
166
  export async function takeCensus(root) {
126
167
  const table = buildTable({ css: "", source: "yours" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.35",
3
+ "version": "0.16.36",
4
4
  "description": "Bring SynthesisUI design systems into any project - tokens, typed components, whole pages and an agent-ready CLAUDE.md manifest.",
5
5
  "type": "module",
6
6
  "bin": {