synthesisui 0.16.496 → 0.16.497
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/claude-md.js +8 -2
- package/dist/commands/landing.js +47 -0
- package/dist/commands/mcp.js +12 -1
- package/dist/commands/use.js +11 -0
- package/dist/index.js +15 -0
- package/dist/install-marks.js +6 -1
- package/dist/registry.js +24 -0
- package/package.json +1 -1
package/dist/claude-md.js
CHANGED
|
@@ -463,6 +463,12 @@ written now** - read the code before you edit it, never a remembered signature.`
|
|
|
463
463
|
* as duas portas e a regra que as mantém fechadas no dia a dia: quem cria sem pedir continua livre.
|
|
464
464
|
* Basta o servidor registrado - a preferência não depende do sistema instalado.
|
|
465
465
|
*/
|
|
466
|
+
/**
|
|
467
|
+
* O PEDIDO LIVRE SAI MASTIGADO (jornada "o pedido livre sai mastigado", E03, 15/10): uma landing pedida em palavras
|
|
468
|
+
* livres passa pelo `landing` antes de qualquer linha - ele lista as seções do catálogo e devolve o prompt da pilha, com
|
|
469
|
+
* as decisões tomadas. Sem servidor também: o `landing` fala com o registro direto.
|
|
470
|
+
*/
|
|
471
|
+
const landingLine = '\n\n**A landing asked in free words:** run `npx synthesisui@latest landing <slug> "<their words>"` first, and follow it.';
|
|
466
472
|
const preferencesLine = recall.available
|
|
467
473
|
? `
|
|
468
474
|
|
|
@@ -523,7 +529,7 @@ If nothing covers it, say which indexed entry you considered and why it did not
|
|
|
523
529
|
project's OWN custom properties, exactly as the guide lists them. Do not write raw colours,
|
|
524
530
|
spacings or radii that a token already covers, and do not invent a new token silently - say so
|
|
525
531
|
instead, because a new token is a decision for a person to make. There is no component
|
|
526
|
-
manifest for an adopted system - the tokens ARE the contract.${theirsLine}${selfCheck}`
|
|
532
|
+
manifest for an adopted system - the tokens ARE the contract.${theirsLine}${landingLine}${selfCheck}`
|
|
527
533
|
: `**When creating or editing components, read the system's GUIDE.md and follow it:** use the
|
|
528
534
|
vocabulary it lists - every name in it is a name THIS project already declares, written exactly as
|
|
529
535
|
you would write it. Do not use raw values outside the system's scale, and never a name from a
|
|
@@ -559,7 +565,7 @@ still yours: the \`request_component\` MCP tool, or \`npx synthesisui@latest req
|
|
|
559
565
|
what the system's author works from - a refusal said only in chat evaporates. If you want to eyeball a
|
|
560
566
|
component on its own, an isolated scratch page is optional and never required - and if you make
|
|
561
567
|
one, put it somewhere that does not become a route in this app, and delete it when you are done.
|
|
562
|
-
Do not apply a component to real production pages unless asked.${selfCheck}`;
|
|
568
|
+
Do not apply a component to real production pages unless asked.${landingLine}${selfCheck}`;
|
|
563
569
|
const locale = await readInterfaceLanguage(projectRoot);
|
|
564
570
|
const language = locale === null
|
|
565
571
|
? ""
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { resolveRegistry } from "../config.js";
|
|
2
|
+
import { fetchLandingParts, fetchLandingPrompt } from "../registry.js";
|
|
3
|
+
/**
|
|
4
|
+
* `synthesisui landing <slug> "<pedido>"` - O PEDIDO LIVRE SAI MASTIGADO (jornada "o pedido livre sai mastigado", 15/10).
|
|
5
|
+
*
|
|
6
|
+
* Em dois passos, e o agente faz os dois:
|
|
7
|
+
*
|
|
8
|
+
* sem --sections a lista das seções de landing do catálogo, com o lugar, o tipo e o nome, e o que fazer em seguida
|
|
9
|
+
* com --sections o MESMO prompt do "Copy prompt" da pilha para essas seções - um template por seção, fontes, menu do
|
|
10
|
+
* celular -, com o conteúdo vindo do pedido
|
|
11
|
+
*
|
|
12
|
+
* A única decisão que fica com o agente é escolher da lista; o resto é regra nossa, já tomada. Fala com o registro
|
|
13
|
+
* (a mesma fonte do site), por isso não é o `use`, que promete não usar a rede (`architecture/no-network.spec.ts`).
|
|
14
|
+
*/
|
|
15
|
+
export async function landing(slug, requestText, opts) {
|
|
16
|
+
const base = resolveRegistry(opts.registry);
|
|
17
|
+
const request = requestText.trim() || "a landing page";
|
|
18
|
+
const chosen = (opts.sections ?? "")
|
|
19
|
+
.split(",")
|
|
20
|
+
.map((s) => s.trim())
|
|
21
|
+
.filter(Boolean);
|
|
22
|
+
if (chosen.length === 0) {
|
|
23
|
+
const parts = await fetchLandingParts(base, slug);
|
|
24
|
+
const byPlace = (place) => parts.filter((p) => p.place === place);
|
|
25
|
+
const line = (p) => ` ${p.id.padEnd(20)} ${p.type} · ${p.name}${p.note ? ` (${p.note})` : ""}`;
|
|
26
|
+
const out = [
|
|
27
|
+
`The landing sections of "${slug}". Pick one navigation, one hero, the body sections in order, and one footer -`,
|
|
28
|
+
"the ones that fit this request:",
|
|
29
|
+
` "${request}"`,
|
|
30
|
+
"",
|
|
31
|
+
"Top",
|
|
32
|
+
...byPlace("nav").map(line),
|
|
33
|
+
"Hero",
|
|
34
|
+
...byPlace("hero").map(line),
|
|
35
|
+
"Body",
|
|
36
|
+
...byPlace("body").map(line),
|
|
37
|
+
"Bottom",
|
|
38
|
+
...byPlace("footer").map(line),
|
|
39
|
+
"",
|
|
40
|
+
"Then run, with your picks in page order, and follow the prompt it prints:",
|
|
41
|
+
` npx synthesisui@latest landing ${slug} --sections <nav>,<hero>,<body...>,<footer> "${request}"`,
|
|
42
|
+
];
|
|
43
|
+
console.log(out.join("\n"));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
console.log(await fetchLandingPrompt(base, slug, chosen, request));
|
|
47
|
+
}
|
package/dist/commands/mcp.js
CHANGED
|
@@ -1966,7 +1966,18 @@ cli) {
|
|
|
1966
1966
|
const prefs = await fetchPreferences({ base: resolveRegistry(), token }, kind, section, await installedSlug(root));
|
|
1967
1967
|
if ("failed" in prefs)
|
|
1968
1968
|
return fromContract(`Their preferences could not be read: ${prefs.failed}. Build with the system as usual and say so in one line.`);
|
|
1969
|
-
|
|
1969
|
+
const answer = preferencesAnswer(kind, prefs, await readSelection(root), await readOff(root));
|
|
1970
|
+
/**
|
|
1971
|
+
* O PEDIDO LIVRE SAI MASTIGADO (jornada "o pedido livre sai mastigado", E03, 15/10): a landing inteira passa pelo
|
|
1972
|
+
* `landing`, que escolhe do catálogo e devolve o prompt com as decisões tomadas. Mora AQUI, e não no CLAUDE.md, porque
|
|
1973
|
+
* com o servidor o bloco tem orçamento (`claude-md.f0.spec.ts`) e esta é a ferramenta que o agente já chama antes de
|
|
1974
|
+
* uma página. Uma parte só (`section`) não passa por ele: é uma seção, e o pedido é dela.
|
|
1975
|
+
*/
|
|
1976
|
+
if (kind === "landing" && section === undefined) {
|
|
1977
|
+
const slug = (await installedSlug(root)) ?? "<slug>";
|
|
1978
|
+
answer.body = `For the whole landing, first run \`npx synthesisui@latest landing ${slug} "<their words>"\`: pick the sections it lists, run it again with \`--sections\`, and build from the prompt it prints - every decision in it is already made. Apply what follows on top of it.\n\n${answer.body}`;
|
|
1979
|
+
}
|
|
1980
|
+
return answer;
|
|
1970
1981
|
}
|
|
1971
1982
|
case "remember_preference": {
|
|
1972
1983
|
const { kind, layer } = args;
|
package/dist/commands/use.js
CHANGED
|
@@ -97,9 +97,20 @@ export async function use(slug, intent, opts) {
|
|
|
97
97
|
`(\`npx synthesisui component ${slug} <name>\`) and use this project's own Tailwind utilities ` +
|
|
98
98
|
`(${utilities}…). Never use raw hex/px outside the system's scale.`;
|
|
99
99
|
const task = intent.trim() || "build the UI I describe next";
|
|
100
|
+
/**
|
|
101
|
+
* UMA LANDING TEM CAMINHO PRÓPRIO (jornada "o pedido livre sai mastigado", E01, 15/10): o `landing` devolve as seções do
|
|
102
|
+
* catálogo e o prompt com as decisões tomadas. O `use` não busca nada - ele promete não usar a rede -, só aponta.
|
|
103
|
+
*/
|
|
104
|
+
const isLanding = /\blanding\b|\bhome ?page\b/i.test(task);
|
|
100
105
|
const prompt = [
|
|
101
106
|
`Use the "${name}" design system (slug: ${slug}, v${version}) to: ${task}`,
|
|
102
107
|
"",
|
|
108
|
+
...(isLanding
|
|
109
|
+
? [
|
|
110
|
+
`This is a landing page: before writing anything, run \`npx synthesisui@latest landing ${slug} "${task.replace(/"/g, "'")}"\` - it lists the catalog's sections for you to pick, then prints the full prompt with every decision made. Follow that prompt instead of the rest of this one.`,
|
|
111
|
+
"",
|
|
112
|
+
]
|
|
113
|
+
: []),
|
|
103
114
|
"Read these files in the project first (highest authority first):",
|
|
104
115
|
...readFirst,
|
|
105
116
|
"",
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import { generate } from "./commands/generate.js";
|
|
|
20
20
|
import { hook } from "./commands/hook.js";
|
|
21
21
|
import { runImport } from "./commands/import.js";
|
|
22
22
|
import { init } from "./commands/init.js";
|
|
23
|
+
import { landing } from "./commands/landing.js";
|
|
23
24
|
import { list } from "./commands/list.js";
|
|
24
25
|
import { login } from "./commands/login.js";
|
|
25
26
|
import { logout } from "./commands/logout.js";
|
|
@@ -61,6 +62,7 @@ Usage - deterministic, FREE:
|
|
|
61
62
|
synthesisui upgrade <slug> update an installed DS + regenerate your components + migration brief
|
|
62
63
|
synthesisui colours [slug] write the colours you chose on the site into your CSS, in your names (asks first)
|
|
63
64
|
synthesisui use <slug> "<intent>" print a ready-to-paste agent prompt to build/modify on-system
|
|
65
|
+
synthesisui landing <slug> "<request>" the catalog's landing sections, then (--sections a,b,c) the prompt with every decision made
|
|
64
66
|
synthesisui clean [--force] strip create-next-app boilerplate (dry run without --force)
|
|
65
67
|
|
|
66
68
|
Usage - governance (deterministic, FREE):
|
|
@@ -719,6 +721,19 @@ async function main() {
|
|
|
719
721
|
});
|
|
720
722
|
break;
|
|
721
723
|
}
|
|
724
|
+
case "landing": {
|
|
725
|
+
const slug = args[0];
|
|
726
|
+
if (!slug) {
|
|
727
|
+
console.error('error: provide the slug and your request - `synthesisui landing <slug> "<request>"`');
|
|
728
|
+
process.exitCode = 1;
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
await landing(slug, args.slice(1).join(" "), {
|
|
732
|
+
sections: typeof flags.sections === "string" ? flags.sections : undefined,
|
|
733
|
+
registry: typeof flags.registry === "string" ? flags.registry : undefined,
|
|
734
|
+
});
|
|
735
|
+
break;
|
|
736
|
+
}
|
|
722
737
|
case "use": {
|
|
723
738
|
const slug = args[0];
|
|
724
739
|
if (!slug) {
|
package/dist/install-marks.js
CHANGED
|
@@ -328,7 +328,12 @@
|
|
|
328
328
|
* 0.16.492 -> 0.16.493 em 06/10, e o passo 1 dá **SIM** ("a galeria aprende", E02): o `init` declara as durações do
|
|
329
329
|
* sistema no @theme (`--duration-fast`), e o blueprint as escreve pelo nome. Um componente escrito antes traz `100ms`.
|
|
330
330
|
*/
|
|
331
|
-
|
|
331
|
+
/**
|
|
332
|
+
* 0.16.494 -> 0.16.497 em 15/10, e o passo 1 dá **SIM** (o pedido livre sai mastigado, E03): o bloco do `CLAUDE.md` sem o
|
|
333
|
+
* servidor diz que uma landing pedida em palavras livres passa primeiro pelo `landing`. Uma pasta escrita antes deixa o
|
|
334
|
+
* agente decidir a página inteira sozinho.
|
|
335
|
+
*/
|
|
336
|
+
export const MATERIALISER_SINCE = "0.16.497";
|
|
332
337
|
/**
|
|
333
338
|
* A ÚLTIMA VERSÃO EM QUE O QUE O HOOK RODA MUDOU.
|
|
334
339
|
*
|
package/dist/registry.js
CHANGED
|
@@ -230,3 +230,27 @@ export async function postSaveComponent(base, payload) {
|
|
|
230
230
|
}
|
|
231
231
|
return (await res.json());
|
|
232
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* O PEDIDO LIVRE SAI MASTIGADO (jornada "o pedido livre sai mastigado", 15/10): a lista de seções de landing do catálogo
|
|
235
|
+
* e o prompt da pilha para as escolhidas. Os dois saem do registro - a mesma fonte do site -, e nunca de uma cópia aqui.
|
|
236
|
+
*/
|
|
237
|
+
export async function fetchLandingParts(base, slug) {
|
|
238
|
+
const url = new URL(`${base}/api/registry/ds/${encodeURIComponent(slug)}`);
|
|
239
|
+
url.searchParams.set("landing", "parts");
|
|
240
|
+
const res = await request(url.toString());
|
|
241
|
+
const body = (await res.json().catch(() => ({})));
|
|
242
|
+
if (!res.ok || !body.parts)
|
|
243
|
+
throw new RegistryError(body.message ?? `Registry responded ${res.status} for "${slug}".`);
|
|
244
|
+
return body.parts;
|
|
245
|
+
}
|
|
246
|
+
export async function fetchLandingPrompt(base, slug, sections, requestText) {
|
|
247
|
+
const url = new URL(`${base}/api/registry/ds/${encodeURIComponent(slug)}`);
|
|
248
|
+
url.searchParams.set("landing", "prompt");
|
|
249
|
+
url.searchParams.set("sections", sections.join(","));
|
|
250
|
+
url.searchParams.set("request", requestText);
|
|
251
|
+
const res = await request(url.toString());
|
|
252
|
+
const body = (await res.json().catch(() => ({})));
|
|
253
|
+
if (!res.ok || !body.prompt)
|
|
254
|
+
throw new RegistryError(body.message ?? `Registry responded ${res.status} for "${slug}".`);
|
|
255
|
+
return body.prompt;
|
|
256
|
+
}
|
package/package.json
CHANGED