synthesisui 0.16.239 → 0.16.241
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/dist/anatomy-read.js +15 -0
- package/dist/commands/import.js +18 -7
- package/dist/install-marks.js +19 -2
- package/dist/skill-import.js +1 -1
- package/dist/stack.js +79 -17
- package/package.json +1 -1
package/dist/anatomy-read.js
CHANGED
|
@@ -417,6 +417,7 @@ sxSpacing) {
|
|
|
417
417
|
(kind === "headless" || kind === "motion" || kind === "icon")) {
|
|
418
418
|
node_.from = measured.from;
|
|
419
419
|
node_.refName = measured.tag;
|
|
420
|
+
// a versão vem do apanhador geral abaixo - um lugar só, depois de todos os ramos
|
|
420
421
|
}
|
|
421
422
|
}
|
|
422
423
|
/**
|
|
@@ -431,6 +432,20 @@ sxSpacing) {
|
|
|
431
432
|
if (measured?.motionProps)
|
|
432
433
|
node_.motionProps = measured.motionProps;
|
|
433
434
|
}
|
|
435
|
+
/**
|
|
436
|
+
* TODO NÓ COM PACOTE LEVA A VERSÃO - o apanhador geral, depois de todos os ramos.
|
|
437
|
+
*
|
|
438
|
+
* A costura já falhou QUATRO vezes ramo a ramo (frontier-kind, import 09/08, o ramo de
|
|
439
|
+
* fronteira, o ramo icon/motion), porque cada caminho novo que carimba `from` esquecia de
|
|
440
|
+
* carimbar a versão. Medido no caminho DERIVADO em 16/08: base-ui com 1 de 23 nós
|
|
441
|
+
* versionados e lucide com 11 de 45 - os nós nasciam no `anatomyFromSketch` com `from` e
|
|
442
|
+
* sem versão, e nenhum ramo daqui os alcançava. Um lugar só, depois de todos.
|
|
443
|
+
*/
|
|
444
|
+
if (node_.from && !node_.version) {
|
|
445
|
+
const v = deps?.[packageRoot(String(node_.from))] ?? deps?.[String(node_.from)];
|
|
446
|
+
if (v)
|
|
447
|
+
node_.version = v;
|
|
448
|
+
}
|
|
434
449
|
// The NAME is what carries the styles, so it is claimed even when nothing
|
|
435
450
|
// resolved: the tree triggers on presence, and structure is most of the
|
|
436
451
|
// value. A node with no name is pure structure and that is legitimate.
|
package/dist/commands/import.js
CHANGED
|
@@ -36,7 +36,7 @@ import { frontierKind, packageRoot } from "../frontier-kind.js";
|
|
|
36
36
|
import { withLibraryStructure } from "../library-structure.js";
|
|
37
37
|
import { body, paint, section } from "../output.js";
|
|
38
38
|
import { phase, startProgress } from "../progress.js";
|
|
39
|
-
import { detectStack, resolveDeps } from "../stack.js";
|
|
39
|
+
import { detectStack, resolveDeps, stackVersions } from "../stack.js";
|
|
40
40
|
import { walk, walkAll } from "./doctor.js";
|
|
41
41
|
/**
|
|
42
42
|
* How many distinct values travel, PER KIND.
|
|
@@ -1739,18 +1739,23 @@ export async function takeCensus(root, opts) {
|
|
|
1739
1739
|
}));
|
|
1740
1740
|
const pkgRaw = await readFile(join(root, "package.json"), "utf8").catch(() => null);
|
|
1741
1741
|
let name = null;
|
|
1742
|
-
/** Their pinned ranges, so a library signal cites the version rather than going stale. */
|
|
1743
|
-
let versions = {};
|
|
1744
1742
|
if (pkgRaw) {
|
|
1745
1743
|
try {
|
|
1746
|
-
|
|
1747
|
-
name = pkg.name ?? null;
|
|
1748
|
-
versions = { ...pkg.devDependencies, ...pkg.dependencies };
|
|
1744
|
+
name = JSON.parse(pkgRaw).name ?? null;
|
|
1749
1745
|
}
|
|
1750
1746
|
catch {
|
|
1751
1747
|
// an unreadable package.json costs the name, not the run
|
|
1752
1748
|
}
|
|
1753
1749
|
}
|
|
1750
|
+
/**
|
|
1751
|
+
* Their pinned ranges, so a library signal cites the version rather than going stale.
|
|
1752
|
+
*
|
|
1753
|
+
* PELO RESOLVEDOR, nunca pela leitura crua de um nível: com `--scope packages/ui` este `root` é a
|
|
1754
|
+
* pasta do escopo, cujo manifesto tem ZERO deps - e 15 de 15 bibliotecas do censo vivo saíam sem
|
|
1755
|
+
* versão (medido 16/08). `resolveDeps` sobe até a raiz do workspace e anda para os irmãos que os
|
|
1756
|
+
* `workspaces` declaram, que é onde recharts/chakra/mui realmente moram.
|
|
1757
|
+
*/
|
|
1758
|
+
const versions = await resolveDeps(root).catch(() => ({}));
|
|
1754
1759
|
finishSignals(signals, importTally, versions);
|
|
1755
1760
|
// Every name their CSS defines, from the same harvest the token table came
|
|
1756
1761
|
// from - so a reference is judged against what actually exists, not against
|
|
@@ -1862,7 +1867,13 @@ export async function takeCensus(root, opts) {
|
|
|
1862
1867
|
const classStyle = detectClassStyle(sources);
|
|
1863
1868
|
return {
|
|
1864
1869
|
census: 1,
|
|
1865
|
-
project: {
|
|
1870
|
+
project: {
|
|
1871
|
+
name,
|
|
1872
|
+
stack: await detectStack(root),
|
|
1873
|
+
...(Object.keys(stackVersions(versions)).length > 0
|
|
1874
|
+
? { versions: stackVersions(versions) }
|
|
1875
|
+
: {}),
|
|
1876
|
+
},
|
|
1866
1877
|
declared: Object.fromEntries(table.byName),
|
|
1867
1878
|
...(Object.keys(keyframes).length > 0 ? { keyframes } : {}),
|
|
1868
1879
|
...(animations.size > 0 ? { animations: [...animations].sort() } : {}),
|
package/dist/install-marks.js
CHANGED
|
@@ -89,7 +89,18 @@
|
|
|
89
89
|
* "YOUR tokens, under YOUR names"). É a fatia de CLI da decisão de 16/08: toda superfície fala a
|
|
90
90
|
* língua do cliente.
|
|
91
91
|
*/
|
|
92
|
-
|
|
92
|
+
/**
|
|
93
|
+
* 0.16.239 -> 0.16.241 em 16/08, e é SIM: o arquivo que cai na pasta dele muda de CONDUTA, não de
|
|
94
|
+
* bytes decorativos. O stub de `sui-import-ds` respondia ao 401 do playbook com "run
|
|
95
|
+
* `npx synthesisui login` and call it again" - o que faz o agente parar a conversa e cobrar uma conta
|
|
96
|
+
* antes de mostrar um único número do repo dele. O `import --dry` nunca precisou de conta (ele
|
|
97
|
+
* retorna antes de ler credenciais), então o stub novo manda MEDIR primeiro, ler o censo de volta nos
|
|
98
|
+
* nomes dele, e só então pedir o login - e, para o MCP ausente, exigir sessão NOVA em vez de sugerir
|
|
99
|
+
* uma nova tentativa que não pode funcionar.
|
|
100
|
+
*
|
|
101
|
+
* Quem instalou antes desta versão tem o stub que estanca: o `upgrade`/`connect` é o que alcança.
|
|
102
|
+
*/
|
|
103
|
+
export const MATERIALISER_SINCE = "0.16.241";
|
|
93
104
|
/**
|
|
94
105
|
* A ÚLTIMA VERSÃO EM QUE O QUE O HOOK RODA MUDOU.
|
|
95
106
|
*
|
|
@@ -184,8 +195,14 @@ export const CHECKER_SINCE = "0.16.232";
|
|
|
184
195
|
* comparação com UM literal, e a divisão do motivo as tirou dele em silêncio
|
|
185
196
|
*
|
|
186
197
|
* Um censo medido antes disto carrega as duas leituras erradas.
|
|
198
|
+
*
|
|
199
|
+
* 0.16.240 a VERSÃO passa a viajar (fase B1, 16/08): `project.versions` (frameworks pinados),
|
|
200
|
+
* 15 de 15 `signals.libraries` com versão (o leitor de manifesto lia o package.json
|
|
201
|
+
* do ESCOPO, que tinha zero deps), e todo nó de fronteira com pacote carimba o range
|
|
202
|
+
* (era 53% no melhor caminho; o derivado dava 38%). Um censo medido antes disto não
|
|
203
|
+
* tem versão nenhuma - e o mapa de blueprints por versão não tem o que consultar.
|
|
187
204
|
*/
|
|
188
|
-
export const READER_SINCE = "0.16.
|
|
205
|
+
export const READER_SINCE = "0.16.240";
|
|
189
206
|
/**
|
|
190
207
|
* O QUE ESTÁ INSTALADO AQUI FICOU PARA TRÁS - e as DUAS condições que fazem isso ser verdade.
|
|
191
208
|
*
|
package/dist/skill-import.js
CHANGED
|
@@ -12,4 +12,4 @@
|
|
|
12
12
|
* invocada, e ela não é segredo - a esteira é.
|
|
13
13
|
*/
|
|
14
14
|
export const IMPORT_SKILL_PATH = ".claude/skills/sui-import-ds/SKILL.md";
|
|
15
|
-
export const IMPORT_SKILL = '---\nname: sui-import-ds\ndescription: Turn a codebase the user ALREADY has into a SynthesisUI design system. Use when someone points at an existing repo, app or component library and asks to import it, adopt it, bring it in, or "make a design system from this" (e.g. "/sui-import-ds", "importa o meu packages/ui", "turn this app into a design system"). Drives the full pipeline - measurement \u2192 your reading of the app \u2192 import \u2192 upgrade proposal - and answers the questions arithmetic cannot.\n---\n\n# Import Design System - served live\n\nThis playbook is served from the platform, not shipped in this file - it is\nalways current, and your context only carries the step you are on.\n\n1. Call the `playbook` tool on the `synthesisui` MCP server with\n { "skill": "import" } - you get the framing and a table of contents.\n2. Fetch ONLY the chapter for the step you are on:\n { "skill": "import", "section": "<id from the toc>" }. Never fetch more\n than the current step needs.\n3. Follow it exactly. When the step is done, fetch the next chapter.\n\
|
|
15
|
+
export const IMPORT_SKILL = '---\nname: sui-import-ds\ndescription: Turn a codebase the user ALREADY has into a SynthesisUI design system. Use when someone points at an existing repo, app or component library and asks to import it, adopt it, bring it in, or "make a design system from this" (e.g. "/sui-import-ds", "importa o meu packages/ui", "turn this app into a design system"). Drives the full pipeline - measurement \u2192 your reading of the app \u2192 import \u2192 upgrade proposal - and answers the questions arithmetic cannot.\n---\n\n# Import Design System - served live\n\nThis playbook is served from the platform, not shipped in this file - it is\nalways current, and your context only carries the step you are on.\n\n1. Call the `playbook` tool on the `synthesisui` MCP server with\n { "skill": "import" } - you get the framing and a table of contents.\n2. Fetch ONLY the chapter for the step you are on:\n { "skill": "import", "section": "<id from the toc>" }. Never fetch more\n than the current step needs.\n3. Follow it exactly. When the step is done, fetch the next chapter.\n\n## If something is missing, they skipped a step - do not stall them\n\nThe supported order is `login`, then `connect`, then open this session. When\nit was followed, neither case below happens.\n\nNOT SIGNED IN. Do not stop and wait. Measure first, so they see their own\nrepo before being asked for anything:\n\n1. Run `npx synthesisui@latest import --dry` - it is local, free, needs no\n account, and writes `_synthesisui/census.json`.\n2. Read that file and tell them what is in THEIR repo, in THEIR names: how\n many declarations, how many components, how much already runs on tokens.\n3. Then: "to turn this into a system on your account, run\n `npx synthesisui@latest login` and tell me when it is done."\n\nNO `synthesisui` MCP SERVER AT ALL. Tell them to run\n`npx synthesisui@latest connect` and then START A NEW SESSION - tools are read\nwhen a session opens, so this one cannot pick it up. Say it plainly and stop\nthere; carrying on in a session that cannot reach the playbook is guessing.\n';
|
package/dist/stack.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* One implementation, because two detectors that disagreed would put a rule in a
|
|
10
10
|
* project the census said was something else.
|
|
11
11
|
*/
|
|
12
|
-
import { readFile } from "node:fs/promises";
|
|
12
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
/**
|
|
15
15
|
* Dependencies as the project actually resolves them - which means reading
|
|
@@ -19,36 +19,98 @@ import { join } from "node:path";
|
|
|
19
19
|
* Next + React + Tailwind app, because a workspace hoists those to the root and
|
|
20
20
|
* the leaf package.json lists only its own icons. Three levels up covers every
|
|
21
21
|
* pnpm/npm workspace layout without wandering into someone's home directory.
|
|
22
|
+
*
|
|
23
|
+
* E PARA OS LADOS TAMBÉM, pelos `workspaces` do manifesto que os declara. Subir
|
|
24
|
+
* sozinho deixou 15 de 15 bibliotecas do censo vivo sem versão (16/08): o escopo
|
|
25
|
+
* era `packages/ui` (zero deps) e recharts/chakra/mui moram em `apps/*`, um
|
|
26
|
+
* IRMÃO - invisível para uma caminhada que só sobe. O componente medido vem do
|
|
27
|
+
* app que usa o sistema, então o manifesto daquele app é evidência tanto quanto
|
|
28
|
+
* o da raiz.
|
|
22
29
|
*/
|
|
23
30
|
export async function resolveDeps(root) {
|
|
24
31
|
const deps = {};
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
const workspaceDirs = [];
|
|
33
|
+
const readManifest = async (dir) => {
|
|
27
34
|
const raw = await readFile(join(dir, "package.json"), "utf8").catch(() => null);
|
|
28
|
-
if (raw)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
if (!raw)
|
|
36
|
+
return;
|
|
37
|
+
try {
|
|
38
|
+
const p = JSON.parse(raw);
|
|
39
|
+
// The nearest package.json wins on a version clash; we only ever ask
|
|
40
|
+
// whether a name is present, so first-seen is enough. The up-chain is
|
|
41
|
+
// read before any sibling, so siblings only ever FILL, never override.
|
|
42
|
+
for (const [k, v] of Object.entries({
|
|
43
|
+
...p.dependencies,
|
|
44
|
+
...p.devDependencies,
|
|
45
|
+
})) {
|
|
46
|
+
if (deps[k] == null)
|
|
47
|
+
deps[k] = String(v);
|
|
40
48
|
}
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
const globs = Array.isArray(p.workspaces)
|
|
50
|
+
? p.workspaces
|
|
51
|
+
: Array.isArray(p.workspaces?.packages)
|
|
52
|
+
? p.workspaces.packages
|
|
53
|
+
: [];
|
|
54
|
+
for (const g of globs) {
|
|
55
|
+
if (typeof g !== "string")
|
|
56
|
+
continue;
|
|
57
|
+
// Only the two shapes real manifests use: `packages/*` and a literal
|
|
58
|
+
// path. Anything fancier is skipped rather than guessed at.
|
|
59
|
+
if (g.endsWith("/*")) {
|
|
60
|
+
const parent = join(dir, g.slice(0, -2));
|
|
61
|
+
const children = await readdir(parent, {
|
|
62
|
+
withFileTypes: true,
|
|
63
|
+
}).catch(() => []);
|
|
64
|
+
for (const c of children)
|
|
65
|
+
if (c.isDirectory())
|
|
66
|
+
workspaceDirs.push(join(parent, c.name));
|
|
67
|
+
}
|
|
68
|
+
else if (!g.includes("*")) {
|
|
69
|
+
workspaceDirs.push(join(dir, g));
|
|
70
|
+
}
|
|
43
71
|
}
|
|
44
72
|
}
|
|
73
|
+
catch {
|
|
74
|
+
// unreadable manifest costs the detection, not the run
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
let dir = root;
|
|
78
|
+
for (let up = 0; up < 4; up++) {
|
|
79
|
+
await readManifest(dir);
|
|
45
80
|
const parent = join(dir, "..");
|
|
46
81
|
if (parent === dir)
|
|
47
82
|
break;
|
|
48
83
|
dir = parent;
|
|
49
84
|
}
|
|
85
|
+
for (const w of workspaceDirs)
|
|
86
|
+
await readManifest(w);
|
|
50
87
|
return deps;
|
|
51
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* OS FRAMEWORKS DO PROJETO, COM A VERSÃO PINADA - o que `Census.project.versions` carrega.
|
|
91
|
+
*
|
|
92
|
+
* `detectStack` colapsa `next@16.0.8` na string `"next"`, e nada no censo guardava versão de
|
|
93
|
+
* framework nenhuma (medido 16/08: zero em todos os campos). Curado de propósito: framework aqui,
|
|
94
|
+
* biblioteca por biblioteca em `signals.libraries` - duas listas com dois papéis, nunca o
|
|
95
|
+
* package.json inteiro dentro do censo.
|
|
96
|
+
*/
|
|
97
|
+
const STACK_PACKAGES = [
|
|
98
|
+
"next",
|
|
99
|
+
"react",
|
|
100
|
+
"react-dom",
|
|
101
|
+
"vue",
|
|
102
|
+
"svelte",
|
|
103
|
+
"vite",
|
|
104
|
+
"tailwindcss",
|
|
105
|
+
"typescript",
|
|
106
|
+
];
|
|
107
|
+
export function stackVersions(deps) {
|
|
108
|
+
const out = {};
|
|
109
|
+
for (const name of STACK_PACKAGES)
|
|
110
|
+
if (deps[name])
|
|
111
|
+
out[name] = deps[name];
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
52
114
|
export async function detectStack(root) {
|
|
53
115
|
const stack = [];
|
|
54
116
|
const has = async (f) => (await readFile(join(root, f), "utf8").catch(() => null)) !== null;
|
package/package.json
CHANGED