synthesisui 0.16.369 → 0.16.370

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.
@@ -554,6 +554,16 @@ export async function add(slug, opts) {
554
554
  if (aligned.dropped.length > 0) {
555
555
  console.log(line(` ${aligned.kept} Tailwind utilit${aligned.kept === 1 ? "y" : "ies"} now point at your own decisions; ${aligned.dropped.length} were left alone because the value would be ours (${aligned.dropped.slice(0, 3).join(", ")}${aligned.dropped.length > 3 ? ", …" : ""}) - your classes keep meaning what they mean today.`));
556
556
  }
557
+ /**
558
+ * O CICLO RECUSADO É DITO, e não engolido - senão o cliente lê um número menor sem saber por quê.
559
+ *
560
+ * A folha traz a ponte (`--ease-in-out: var(--ds-motion-easings-in-out)`) para que a utility dele
561
+ * resolva pelo sistema. Apontar de volta fecharia um ciclo, e um ciclo de custom property não deixa
562
+ * o valor errado: invalida a propriedade no elemento e em todos os descendentes. Recusar é o certo,
563
+ * e a linha diz que nada foi perdido - a utility dele continua resolvendo pelo sistema.
564
+ */
565
+ if (theirVars.cycles > 0)
566
+ console.log(` ${theirVars.cycles} ${theirVars.cycles === 1 ? "value" : "values"} already had the bridge pointing the other way, so ${theirVars.cycles === 1 ? "it was" : "they were"} left alone - your own utility still resolves through this system, and pointing back would have cancelled both.`);
557
567
  if (theirVars.pointed > 0)
558
568
  console.log(` ${theirVars.pointed} value${theirVars.pointed === 1 ? "" : "s"} in tokens.css now point at the name YOUR code already gives ${theirVars.pointed === 1 ? "it" : "them"} - change yours and the system follows${theirVars.pruned > 0 ? `; ${theirVars.pruned} matched but your build does not emit ${theirVars.pruned === 1 ? "that name" : "those names"}, so ${theirVars.pruned === 1 ? "it keeps" : "they keep"} the value` : ""}`);
559
569
  /**
@@ -203,7 +203,7 @@ const TOOLS = [
203
203
  },
204
204
  {
205
205
  name: "apply_upgrade",
206
- description: "The optimisation this system can write on its OWN, and the one question to ask before writing it. Call it with { slug } to GET the question - it comes back composed, with their numbers in it, and you deliver it as it is rather than rephrasing it. Only after they say yes, call again with { slug, confirmed: true }. What it writes never adds a word they did not write and never moves a value they chose: a literal only becomes a reference when it resolves to the same value. Everything that would need a NAME from them stays out and comes back counted, so you can say what is still waiting. Do NOT call this with confirmed:true off your own judgement - the whole point of the question is that the answer is theirs.",
206
+ description: "The optimisation this system can write on its OWN, and the one question to ask before writing it. Call it with { slug } to GET the question - it comes back composed, with their numbers in it, and you deliver it as it is rather than rephrasing it. Only after they say yes, call again with { slug, confirmed: true }. What it writes never adds a word they did not write and never moves a value they chose: a literal only becomes a reference when it resolves to the same value. Everything that would need a NAME from them stays out and comes back counted, so you can say what is still waiting. Do NOT call this with confirmed:true off your own judgement - the whole point of the question is that the answer is theirs. AND THIS RUN ENDS WHEN IT IS APPLIED: report what changed in one short block and stop. If you found something else worth doing - a wiring gap, a defect, a fix waiting - name it in ONE line and offer it as a next step, never as a second investigation in the same breath. A run that answers `optimise my design system` with a nine-row impact table and a second three-option decision has buried the result it was asked for: whatever you measured is worth its own turn, where they can arrive with attention instead of spending what is left of it.",
207
207
  inputSchema: {
208
208
  type: "object",
209
209
  properties: {
@@ -170,7 +170,7 @@
170
170
  * O que o cliente ganha ao rodar `upgrade`: o agente dele no Codex passa a poder PERGUNTAR ao
171
171
  * sistema, em vez de só receber as regras e adivinhar o resto.
172
172
  */
173
- export const MATERIALISER_SINCE = "0.16.362";
173
+ export const MATERIALISER_SINCE = "0.16.370";
174
174
  /**
175
175
  * A ÚLTIMA VERSÃO EM QUE O QUE O HOOK RODA MUDOU.
176
176
  *
@@ -101,11 +101,22 @@ export function pointAtTheirNames(css, theirs, resolvable) {
101
101
  * buildou não tem como provar o que resolve, e um par afirmado sem prova é pior que par nenhum.
102
102
  */
103
103
  if (!resolvable || theirs.byName.size === 0)
104
- return { css, pointed: 0, pruned: 0, pairs: [] };
104
+ return { css, pointed: 0, pruned: 0, cycles: 0, pairs: [] };
105
105
  const ours = buildTable({ css, source: "installed" });
106
106
  const alias = theirNames(ours, theirs);
107
+ /**
108
+ * A PONTE QUE JÁ ESTÁ NA FOLHA: o nome DELE -> o nosso token para o qual ele já aponta.
109
+ *
110
+ * Lido da própria folha e não de uma lista, porque quem decide o que é bridgeado é o compilador e a
111
+ * lista dele muda: hoje são famílias, pesos, easings, escala de tipo e gradientes, e amanhã pode ser
112
+ * outra. Uma cópia da regra aqui divergiria no dia em que uma família entrasse lá.
113
+ */
114
+ const bridged = new Map();
115
+ for (const [, theirName, ourName] of css.matchAll(/^\s*(--[a-zA-Z0-9_-]+)\s*:\s*var\((--ds-[a-zA-Z0-9_-]+)\)\s*;/gm))
116
+ bridged.set(theirName, ourName);
107
117
  let pointed = 0;
108
118
  let pruned = 0;
119
+ let cycles = 0;
109
120
  /** Ver `PointedAt.pairs`: o mapa sai do mesmo casamento que reescreve a linha. */
110
121
  const pairs = [];
111
122
  const out = css.replace(/^(\s*)(--ds-[a-zA-Z0-9_-]+)(\s*:\s*)([^;]+);/gm, (line, indent, name, sep, value) => {
@@ -118,6 +129,15 @@ export function pointAtTheirNames(css, theirs, resolvable) {
118
129
  const theirName = alias.get(`${kind}:${normalizeValue(value.trim(), ours.rootPx)}`)?.name;
119
130
  if (!theirName || theirName === name)
120
131
  return line;
132
+ /**
133
+ * A PONTE JÁ APONTA PARA CÁ - então apontar de volta fecha um ciclo, e um ciclo não deixa o
134
+ * valor errado: deixa a propriedade INVÁLIDA. A utility dele já resolve pelo nosso token, que é
135
+ * o que a ponte existe para fazer, então esta linha não tem nada a ganhar e tudo a perder.
136
+ */
137
+ if (bridged.get(theirName) === name) {
138
+ cycles += 1;
139
+ return line;
140
+ }
121
141
  if (!resolvable.has(theirName)) {
122
142
  pruned += 1;
123
143
  return line;
@@ -126,7 +146,7 @@ export function pointAtTheirNames(css, theirs, resolvable) {
126
146
  pairs.push({ ours: name, theirs: theirName, value: value.trim() });
127
147
  return `${indent}${name}${sep}var(${theirName});`;
128
148
  });
129
- return { css: out, pointed, pruned, pairs };
149
+ return { css: out, pointed, pruned, cycles, pairs };
130
150
  }
131
151
  /**
132
152
  * O PREFIXO DA NOSSA VARIÁVEL -> A FAMÍLIA, e a chave que `theirNames` devolve é `<família>:<valor>`.
@@ -151,7 +171,7 @@ const FAMILY_KIND = {
151
171
  export async function pointTokensAtTheirNames(root, payload) {
152
172
  const css = payload.artifacts["tokens.css"] ?? "";
153
173
  if (!css)
154
- return { css, pointed: 0, pruned: 0, pairs: [] };
174
+ return { css, pointed: 0, pruned: 0, cycles: 0, pairs: [] };
155
175
  const [theirs, resolvable] = await Promise.all([
156
176
  harvestTheirCss(root),
157
177
  resolvableVars(root),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.369",
3
+ "version": "0.16.370",
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": {