synthesisui 0.16.139 → 0.16.141
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 +18 -3
- package/dist/commands/import.js +1 -1
- package/dist/commands/sync.js +145 -1
- package/dist/index.js +19 -4
- package/dist/skill-import.js +15 -0
- package/package.json +1 -1
package/dist/anatomy-read.js
CHANGED
|
@@ -65,9 +65,24 @@ const FRONTIERS = new Set(["component", "external"]);
|
|
|
65
65
|
* its own box, because its styles already sit on the component's base.
|
|
66
66
|
*/
|
|
67
67
|
const STRUCTURAL = /^(root|wrapper|base|el|outer)$/i;
|
|
68
|
-
/**
|
|
69
|
-
*
|
|
70
|
-
|
|
68
|
+
/**
|
|
69
|
+
* A transcrição patológica do DOM de alguém, com teto - e o teto foi medido errado.
|
|
70
|
+
*
|
|
71
|
+
* "Seis níveis alcançam qualquer componente real; além disso são divs de layout até o fim" foi
|
|
72
|
+
* calibrado numa biblioteca de 36 componentes. Um app de 275 desmente: a leitura do
|
|
73
|
+
* `apps/web-dashboard` tem 64 nós além do 6, e a distribuição mostra que a cauda é fina e é
|
|
74
|
+
* CONTEÚDO (05/08):
|
|
75
|
+
*
|
|
76
|
+
* nível 0 1 2 3 4 5 6 7 8 9
|
|
77
|
+
* nós 923 935 871 609 405 231 139 50 12 2
|
|
78
|
+
*
|
|
79
|
+
* O que estava acontecendo com esses 64: `walk` retornava ali, então tudo abaixo do sexto nível era
|
|
80
|
+
* descartado em silêncio - a estrutura que o cliente escreveu, perdida sem uma linha de aviso.
|
|
81
|
+
*
|
|
82
|
+
* 10 cobre a população inteira com folga e mantém o teto contra recursão patológica, que é a razão
|
|
83
|
+
* de ele existir. Um número medido em vez de estimado.
|
|
84
|
+
*/
|
|
85
|
+
const MAX_DEPTH = 10;
|
|
71
86
|
/**
|
|
72
87
|
* The same ceiling the sketch measured, for the same reason.
|
|
73
88
|
*
|
package/dist/commands/import.js
CHANGED
|
@@ -2254,7 +2254,7 @@ function rootBehaviour(tag, sketch) {
|
|
|
2254
2254
|
? { rootProps: first.behaviourProps }
|
|
2255
2255
|
: {};
|
|
2256
2256
|
}
|
|
2257
|
-
async function resolveReadParts(census, root) {
|
|
2257
|
+
export async function resolveReadParts(census, root) {
|
|
2258
2258
|
/**
|
|
2259
2259
|
* A READING IS OPTIONAL HERE. THE SKETCH IS NOT.
|
|
2260
2260
|
*
|
package/dist/commands/sync.js
CHANGED
|
@@ -3,8 +3,9 @@ import { join, resolve } from "node:path";
|
|
|
3
3
|
import { readToken, resolveRegistry } from "../config.js";
|
|
4
4
|
import { readEvents } from "../doctor/ledger.js";
|
|
5
5
|
import { checkableName, closeRequest, readRequests, verifyAndCloseRequests, } from "../doctor/requests.js";
|
|
6
|
-
import { body, section } from "../output.js";
|
|
6
|
+
import { body, paint, section } from "../output.js";
|
|
7
7
|
import { repoStateOf } from "../repo-state.js";
|
|
8
|
+
import { resolveReadParts, takeCensus } from "./import.js";
|
|
8
9
|
/**
|
|
9
10
|
* What each decision means ON THIS MACHINE - the card decides, the sync
|
|
10
11
|
* enacts. The web never touches the local file; this line is printed right
|
|
@@ -83,6 +84,19 @@ export async function sync(opts) {
|
|
|
83
84
|
console.log(body("No installed system here, so there is nowhere to sync to."));
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* A MEDIÇÃO NOVA, ANTES DO REGISTRO - e é isto que faz um conserto de leitura alcançar alguém.
|
|
89
|
+
*
|
|
90
|
+
* Um leitor novo do CLI precisa OLHAR o repo: o que a plataforma guarda é o censo, e o fonte fica
|
|
91
|
+
* aqui por decisão de privacidade. Essa passada é irredutível. O que era redutível é a cerimônia -
|
|
92
|
+
* até hoje "re-importar" significava a skill inteira, seis perguntas, e um agente reescrevendo 261
|
|
93
|
+
* anatomias que já estavam gravadas (dono, 05/08).
|
|
94
|
+
*
|
|
95
|
+
* Então: a plataforma devolve o que já foi decidido (o escopo e a leitura), o CLI mede com o leitor
|
|
96
|
+
* ATUAL, funde a leitura no censo fresco, AVISA o que seria reescrito, e envia. Sem entrevista.
|
|
97
|
+
*/
|
|
98
|
+
if (!opts.recordOnly)
|
|
99
|
+
await remeasure({ root, base, token, slug, cli: opts.cli });
|
|
86
100
|
// Verification first, so the snapshot never reports "open" about something
|
|
87
101
|
// the installed css already delivers - a request closes because a machine
|
|
88
102
|
// CHECKED, not because someone remembered to say so (dono, 29/07).
|
|
@@ -152,3 +166,133 @@ export async function sync(opts) {
|
|
|
152
166
|
console.log(body(`The record lives on your system's overview:`));
|
|
153
167
|
console.log(body(` ${base}/dashboard/mine/${slug}`));
|
|
154
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* MEDE DE NOVO, AVISA, E ENVIA - o corpo do `sync` que faz um leitor novo chegar num sistema.
|
|
171
|
+
*
|
|
172
|
+
* A ordem é a lei aqui, e cada passo existe por um caso real:
|
|
173
|
+
*
|
|
174
|
+
* 1. a plataforma devolve o ESCOPO e a LEITURA já gravados. Sem isto, o `sync` teria que
|
|
175
|
+
* perguntar de novo o que já foi decidido, e um agente reescreveria 261 anatomias.
|
|
176
|
+
* 2. mede com o leitor ATUAL - é o único passo que precisa estar nesta máquina, porque o fonte
|
|
177
|
+
* dele não sai daqui.
|
|
178
|
+
* 3. funde a leitura gravada no censo fresco. A anatomia é do agente; a medição é nossa.
|
|
179
|
+
* 4. AVISA antes de enviar o que seria reescrito, e pergunta. Avisar depois de escrever não é
|
|
180
|
+
* avisar.
|
|
181
|
+
* 5. envia para a rota que atualiza o RASCUNHO pelo slug - nada publicado se move.
|
|
182
|
+
*/
|
|
183
|
+
async function remeasure(args) {
|
|
184
|
+
const { root, base, token, slug } = args;
|
|
185
|
+
const head = await fetch(`${base}/api/registry/ds/${slug}/reading`, {
|
|
186
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
187
|
+
}).catch(() => null);
|
|
188
|
+
if (!head?.ok) {
|
|
189
|
+
console.log(section("Sync"));
|
|
190
|
+
console.log(body(head
|
|
191
|
+
? `The registry answered ${head.status} for this system's reading, so nothing was re-measured. The record below still travels.`
|
|
192
|
+
: "Could not reach the registry, so nothing was re-measured. The record below still travels."));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const stored = (await head.json());
|
|
196
|
+
/**
|
|
197
|
+
* SEM CENSO GRAVADO NÃO HÁ O QUE REMEDIR CONTRA. Um sistema que nasceu da galeria não tem escopo
|
|
198
|
+
* nem leitura, e medir o repo dele produziria um censo de um projeto que ninguém mapeou para ele.
|
|
199
|
+
*/
|
|
200
|
+
if (!stored.hasCensus) {
|
|
201
|
+
console.log(section("Sync"));
|
|
202
|
+
console.log(body(`"${slug}" did not come from an import, so there is no measurement to refresh. Import it first: npx synthesisui import`));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
console.log(section("Measuring your repository again"));
|
|
206
|
+
console.log(body(paint.faint(`${stored.scope ? `scope ${stored.scope}` : "the whole repo"} · the reading you already authored travels unchanged`)));
|
|
207
|
+
const census = await takeCensus(stored.scope ? join(root, stored.scope) : root, {
|
|
208
|
+
...(stored.scope ? { scopeLabel: stored.scope } : {}),
|
|
209
|
+
...(args.cli ? { cli: args.cli } : {}),
|
|
210
|
+
/** O `--usage` é EVIDÊNCIA e leva rótulo: sem ele o censo não sabe de que app o número veio. */
|
|
211
|
+
usage: (stored.usage ?? []).map((u) => ({
|
|
212
|
+
path: join(root, u),
|
|
213
|
+
label: u,
|
|
214
|
+
})),
|
|
215
|
+
}).catch(() => null);
|
|
216
|
+
if (!census) {
|
|
217
|
+
console.log(body("The measurement failed, so nothing was sent."));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
/** A LEITURA GRAVADA ENTRA NO CENSO FRESCO - ver a rota `reading`. */
|
|
221
|
+
if (stored.reading)
|
|
222
|
+
census.reading = stored.reading;
|
|
223
|
+
await resolveReadParts(census, root).catch(() => { });
|
|
224
|
+
/**
|
|
225
|
+
* O AVISO, ANTES DE ENVIAR. `edited` são as receitas que uma pessoa escreveu na tela; o cruzamento
|
|
226
|
+
* com o que acabou de ser medido é uma interseção de conjuntos, e é por isso que ele mora aqui em
|
|
227
|
+
* vez de virar um gêmeo da regra que vive na plataforma.
|
|
228
|
+
*/
|
|
229
|
+
const slugOf = (name) => name
|
|
230
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
231
|
+
.toLowerCase()
|
|
232
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
233
|
+
.replace(/^-|-$/g, "");
|
|
234
|
+
const arriving = new Set(Object.keys(census.looks ?? {}).map(slugOf));
|
|
235
|
+
/**
|
|
236
|
+
* SÓ O QUE ESTE ENVIO TOCA. Uma receita que a pessoa editou e que a medição não traz fica onde
|
|
237
|
+
* está, e listá-la seria assustar sem motivo - o erro mais fácil de cometer neste aviso.
|
|
238
|
+
*/
|
|
239
|
+
const hit = (stored.draft?.edited ?? []).filter((e) => arriving.has(e.component));
|
|
240
|
+
if (hit.length > 0) {
|
|
241
|
+
console.log("");
|
|
242
|
+
console.log(section("You have an active draft"));
|
|
243
|
+
console.log(body(stored.draft?.warning ??
|
|
244
|
+
`${hit.length} of the ${stored.draft?.components ?? "?"} components in it were written on the screen, and this send would rewrite them.`));
|
|
245
|
+
console.log(body(paint.faint(hit
|
|
246
|
+
.slice(0, 6)
|
|
247
|
+
.map((e) => `${e.component}${e.at ? ` (${e.at.slice(0, 10)})` : ""}`)
|
|
248
|
+
.join(" · "))));
|
|
249
|
+
if (!(await askToOverwrite())) {
|
|
250
|
+
console.log(body("Nothing was sent. Your draft is untouched."));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const res = await fetch(`${base}/api/registry/ds/${slug}/census`, {
|
|
255
|
+
method: "POST",
|
|
256
|
+
headers: {
|
|
257
|
+
"content-type": "application/json",
|
|
258
|
+
Authorization: `Bearer ${token}`,
|
|
259
|
+
},
|
|
260
|
+
body: JSON.stringify({ census }),
|
|
261
|
+
}).catch(() => null);
|
|
262
|
+
if (!res?.ok) {
|
|
263
|
+
console.log(body(res
|
|
264
|
+
? `The registry answered ${res.status}. Nothing was written.`
|
|
265
|
+
: "Could not reach the registry. Nothing was written."));
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const out = (await res.json());
|
|
269
|
+
console.log("");
|
|
270
|
+
console.log(section("Sent"));
|
|
271
|
+
console.log(body(`${out.written ?? 0} of ${out.total ?? 0} components written.`));
|
|
272
|
+
for (const note of out.notes ?? [])
|
|
273
|
+
console.log(body(paint.faint(note)));
|
|
274
|
+
if (out.url)
|
|
275
|
+
console.log(body(out.url));
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Pergunta uma vez, e só num terminal de verdade.
|
|
279
|
+
*
|
|
280
|
+
* Sem TTY a resposta é NÃO: uma invocação por script que sobrescreve trabalho de alguém porque
|
|
281
|
+
* ninguém estava lá para dizer não é o pior default possível. `--yes` é o caminho explícito.
|
|
282
|
+
*/
|
|
283
|
+
async function askToOverwrite() {
|
|
284
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
285
|
+
return false;
|
|
286
|
+
const { createInterface } = await import("node:readline/promises");
|
|
287
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
288
|
+
try {
|
|
289
|
+
const answer = await rl.question(" send anyway? [y/N]: ");
|
|
290
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
rl.close();
|
|
297
|
+
}
|
|
298
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -54,8 +54,10 @@ Usage - governance (deterministic, FREE):
|
|
|
54
54
|
something no reader would change
|
|
55
55
|
synthesisui request [component|token] the queue of what your agent needed and the system
|
|
56
56
|
refused to invent (--done <id> closes one)
|
|
57
|
-
synthesisui sync
|
|
58
|
-
|
|
57
|
+
synthesisui sync re-measure this repo with the current reader and send it,
|
|
58
|
+
reusing the reading you already authored, plus the local
|
|
59
|
+
record - checks, fixes, open requests (--record-only skips
|
|
60
|
+
the measurement, --yes skips the overwrite question)
|
|
59
61
|
synthesisui hook the check itself; installed by connect, run by your editor
|
|
60
62
|
synthesisui mcp the system as tools; installed by connect, run by your agent
|
|
61
63
|
|
|
@@ -422,8 +424,21 @@ async function main() {
|
|
|
422
424
|
await clean({ dir, force: flags.force === true });
|
|
423
425
|
break;
|
|
424
426
|
case "sync":
|
|
425
|
-
|
|
426
|
-
|
|
427
|
+
/**
|
|
428
|
+
* A versão que reporta o estado do repo - ver `repoStateOf` - e que MEDE: desde 05/08 o `sync`
|
|
429
|
+
* remede o repo com o leitor atual e reenvia, reusando a leitura já gravada. É o único comando
|
|
430
|
+
* do lado do cliente para fazer um conserto de leitura chegar.
|
|
431
|
+
*
|
|
432
|
+
* `--record-only` manda só o registro, e `--yes` não pergunta antes de sobrescrever receita
|
|
433
|
+
* escrita na tela. O default é medir e perguntar.
|
|
434
|
+
*/
|
|
435
|
+
await sync({
|
|
436
|
+
dir,
|
|
437
|
+
registry,
|
|
438
|
+
cli: CLI_VERSION,
|
|
439
|
+
recordOnly: args.includes("--record-only"),
|
|
440
|
+
yes: args.includes("--yes"),
|
|
441
|
+
});
|
|
427
442
|
break;
|
|
428
443
|
case "request": {
|
|
429
444
|
// `synthesisui request` lists; `request component --name x --for "..."`
|
package/dist/skill-import.js
CHANGED
|
@@ -1189,6 +1189,21 @@ three biggest items so they know whether it is worth opening now.
|
|
|
1189
1189
|
found in their code, a token that is not ramp-shaped, a name the document refused. Read them
|
|
1190
1190
|
and pass on the ones that matter.
|
|
1191
1191
|
|
|
1192
|
+
**And the notes now judge YOUR reading, which nothing did before.** \`validate_recipes\` looks at
|
|
1193
|
+
the \`anatomy\` inside a recipe; the anatomy you author travels in \`reading.components[X].anatomy\`,
|
|
1194
|
+
and until 05/08 no one looked at it - so a note may name findings the batch validator never saw.
|
|
1195
|
+
Two kinds, and both are yours to act on:
|
|
1196
|
+
|
|
1197
|
+
- **structure that does not survive the reader.** Nine of these landed on a real import, every one
|
|
1198
|
+
the same shape: a \`button\` holding a \`stack\`. Only \`row\` and \`stack\` arrange, so the children are
|
|
1199
|
+
hoisted out and become siblings - the nesting they wrote is gone. Fix it in the reading and send
|
|
1200
|
+
again; the note tells you the component and the path.
|
|
1201
|
+
- **references pointing at components the system does not contain.** 215 of 660 on that same
|
|
1202
|
+
import. This one is usually NOT a mistake of yours: their component composes something the gate
|
|
1203
|
+
left out, or something outside the scope that was measured. Say the number to the person and name
|
|
1204
|
+
the top few, because a specimen there draws the reference and nothing else - and if the missing
|
|
1205
|
+
piece is central to their system, the answer is a wider \`--scope\`, not a rewritten reading.
|
|
1206
|
+
|
|
1192
1207
|
### 6. Close the loop in their repo
|
|
1193
1208
|
|
|
1194
1209
|
The system is only worth something once it governs the code it came from:
|
package/package.json
CHANGED