synthesisui 0.16.169 → 0.16.170

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.
@@ -136,6 +136,7 @@ export async function add(slug, opts) {
136
136
  version: payload.version,
137
137
  registry: base,
138
138
  fetchedAt: new Date().toISOString(),
139
+ ...(opts.cli ? { cli: opts.cli } : {}),
139
140
  ...(scope ? { scope } : {}),
140
141
  ...(usage.length > 0 ? { usage } : {}),
141
142
  };
@@ -94,6 +94,22 @@ opts = {}) {
94
94
  says: `${events.length} checked write${events.length === 1 ? "" : "s"} recorded here and not sent - the platform is scoring this repo on older evidence.`,
95
95
  run: "npx synthesisui sync",
96
96
  });
97
+ /**
98
+ * O DÉCIMO ESTADO: os ARQUIVOS deste install foram escritos por um CLI anterior.
99
+ *
100
+ * Os nove primeiros nunca cobriram isto, e ele é sorrateiro: o sistema pode estar na ÚLTIMA versão
101
+ * do DS e ter uma pasta escrita por um CLI de dez versões atrás. Em 07/08 foi a doutrina - o `add`
102
+ * de hoje escreve `doctrine.json` e o de ontem materializava dois `.md` -, e o `upgrade` sai sem
103
+ * fazer nada quando não há gap de versão, então nenhum comando alcançava aquele estado.
104
+ *
105
+ * O `connect` conserta na hora (ver `refreshInstall`), e esta linha existe para quem ainda não
106
+ * rodou: a verificação de abertura é o único lugar que fala sem ser perguntado.
107
+ */
108
+ if (cli && lock.cli && lock.cli !== cli)
109
+ out.push({
110
+ says: `the files under _synthesisui/ds/${lock.slug} were written by CLI ${lock.cli} and you are running ${cli} - the design system's version has not changed, but what this CLI writes into that folder has.`,
111
+ run: "npx synthesisui connect",
112
+ });
97
113
  if (cli && lock.version == null)
98
114
  out.push({
99
115
  says: `"${lock.slug}" has no version recorded, so nothing can tell whether the CSS in this repo is the one the platform publishes.`,
@@ -1,10 +1,11 @@
1
- import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
1
+ import { mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
3
  import { wireAgent } from "../agent-wiring.js";
4
4
  import { blockHomes, syncClaudeMd } from "../claude-md.js";
5
5
  import { body, paint, section, snippet } from "../output.js";
6
6
  import { IMPORT_SKILL, IMPORT_SKILL_PATH } from "../skill-import.js";
7
7
  import { INIT_SKILL, INIT_SKILL_PATH } from "../skill-init.js";
8
+ import { add } from "./add.js";
8
9
  import { ci } from "./ci.js";
9
10
  import { MCP_TOOL_COUNT } from "./mcp.js";
10
11
  /**
@@ -28,16 +29,82 @@ import { MCP_TOOL_COUNT } from "./mcp.js";
28
29
  * um cliente que rodou `connect` há um mês não sabe que o nome mudou.
29
30
  */
30
31
  const LEGACY_SKILLS = ["import-design-system"];
32
+ /**
33
+ * OS ARQUIVOS DO INSTALL, PÔSTOS EM DIA COM ESTE CLI.
34
+ *
35
+ * A fiação era reconciliada (hook, MCP, CLAUDE.md, skills) e os arquivos do sistema instalado não.
36
+ * Medido em 07/08: o `add` de hoje serve a doutrina por ferramenta e escreve `doctrine.json`; o de
37
+ * ontem materializava `rules.md` e `philosophy.md`. Um repo que rodou `connect` e `sync` ficava com os
38
+ * dois `.md` velhos, sem `doctrine.json`, sem escopo no `.lock` - e o `upgrade` SAI SEM FAZER NADA
39
+ * quando não há gap de versão, então nenhum dos seis comandos alcançava esse estado.
40
+ *
41
+ * O `connect` é o lugar honesto: é o comando que a pessoa roda quando atualiza o CLI, e a pergunta que
42
+ * ela já está fazendo é "me põe em dia".
43
+ *
44
+ * REMATERIALIZA A MESMA VERSÃO, nunca uma nova: `add` com a `version` que o `.lock` pina. Subir de
45
+ * versão é decisão dela e continua sendo o `upgrade`.
46
+ *
47
+ * SILENCIOSO QUANDO JÁ ESTÁ EM DIA, e sem rede não faz nada - um `connect` que falha por estar num
48
+ * avião seria pior que a defasagem que ele conserta.
49
+ */
50
+ async function refreshInstall(root, cli, registry) {
51
+ const dsDir = join(root, "_synthesisui", "ds");
52
+ const names = await readdir(dsDir, { withFileTypes: true }).catch(() => []);
53
+ for (const entry of names) {
54
+ if (!entry.isDirectory())
55
+ continue;
56
+ const raw = await readFile(join(dsDir, entry.name, ".lock"), "utf8").catch(() => null);
57
+ if (!raw)
58
+ continue;
59
+ let lock;
60
+ try {
61
+ lock = JSON.parse(raw);
62
+ }
63
+ catch {
64
+ continue;
65
+ }
66
+ /** Um DS adotado é descrito aqui e pertencido em outro lugar - não há o que rematerializar. */
67
+ if (!lock.slug || lock.adopted || typeof lock.version !== "number")
68
+ continue;
69
+ if (lock.cli === cli)
70
+ continue;
71
+ const done = await add(lock.slug, {
72
+ ...(registry ? { registry } : {}),
73
+ dir: root,
74
+ version: lock.version,
75
+ setupHints: false,
76
+ cli,
77
+ }).then(() => true, () => false);
78
+ if (!done)
79
+ return null;
80
+ return { slug: lock.slug, ...(lock.cli ? { was: lock.cli } : {}) };
81
+ }
82
+ return null;
83
+ }
31
84
  export async function connect(opts) {
32
85
  const root = opts.dir ?? process.cwd();
33
86
  // Both unless one is explicitly turned off - somebody who says `--no-hook`
34
87
  // means it, and somebody who says nothing wants the thing to work.
35
88
  const want = { hook: opts.hook !== false, mcp: opts.mcp !== false };
89
+ /**
90
+ * OS ARQUIVOS DO INSTALL ANTES DA FIAÇÃO: o `add` reescreve o `CLAUDE.md` por dentro, e o
91
+ * `syncClaudeMd` abaixo tem que ser o último a falar sobre ele.
92
+ */
93
+ const refreshed = await refreshInstall(root, opts.version, opts.registry).catch(() => null);
36
94
  const wired = await wireAgent(root, opts.version, want);
37
95
  // The block reads the settings we just wrote, so it must be regenerated
38
96
  // after them, not before.
39
97
  await syncClaudeMd(root);
40
98
  console.log(section("Connected"));
99
+ /**
100
+ * O QUE ESTE CLI REESCREVEU NA PASTA DO SISTEMA - dito primeiro, porque é o que a pessoa não sabia
101
+ * que estava devendo. Ela rodou `connect` para atualizar a fiação; os arquivos do install estarem
102
+ * velhos era invisível, e o `upgrade` não alcançava (ver `refreshInstall`).
103
+ */
104
+ if (refreshed)
105
+ console.log(body(`✓ _synthesisui/ds/${refreshed.slug}/ rewritten by this CLI${refreshed.was
106
+ ? ` - it was written by ${refreshed.was}`
107
+ : " - it carried no CLI version, so it predates this"}`));
41
108
  if (want.hook) {
42
109
  console.log(body(wired.hook === "added"
43
110
  ? "✓ .claude/settings.json the check now runs after every write"
@@ -125,7 +125,12 @@ export async function upgrade(slug, opts) {
125
125
  }
126
126
  // 1. re-materialize the artifacts (v<latest>/ + root re-exports + .lock);
127
127
  // setup hints suppressed - an upgrade means the app is already wired.
128
- await add(slug, { registry: opts.registry, dir: root, setupHints: false });
128
+ await add(slug, {
129
+ registry: opts.registry,
130
+ dir: root,
131
+ setupHints: false,
132
+ ...(opts.cli ? { cli: opts.cli } : {}),
133
+ });
129
134
  // 2. regenerate YOUR materialized components (the ones `component` wrote)
130
135
  const config = await readProjectConfig(root);
131
136
  const regenerated = [];
package/dist/index.js CHANGED
@@ -241,6 +241,7 @@ async function main() {
241
241
  case "connect":
242
242
  await connect({
243
243
  dir,
244
+ ...(registry ? { registry } : {}),
244
245
  version: CLI_VERSION,
245
246
  hook: flags.hook !== false,
246
247
  mcp: flags.mcp !== false,
@@ -379,7 +380,7 @@ async function main() {
379
380
  return;
380
381
  }
381
382
  }
382
- await add(slug, { registry, dir, version });
383
+ await add(slug, { registry, dir, version, cli: CLI_VERSION });
383
384
  break;
384
385
  }
385
386
  case "login":
@@ -512,6 +513,7 @@ async function main() {
512
513
  await upgrade(slug, {
513
514
  registry,
514
515
  dir,
516
+ cli: CLI_VERSION,
515
517
  force: flags.force === true,
516
518
  from: typeof flags.from === "string" ? Number(flags.from) : undefined,
517
519
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.169",
3
+ "version": "0.16.170",
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": {