synthesisui 0.16.183 → 0.16.185
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/commands/doctor.js +42 -14
- package/dist/doctor/ci-format.js +3 -1
- package/dist/doctor/ledger.js +26 -0
- package/dist/doctor/scan.js +2 -0
- package/dist/repo-state.js +3 -0
- package/package.json +1 -1
package/dist/commands/doctor.js
CHANGED
|
@@ -8,7 +8,7 @@ import { emptyTally, internalSpecifiers, scanComponentsInto, tallyToInventory, }
|
|
|
8
8
|
import { checkContracts } from "../doctor/contract-check.js";
|
|
9
9
|
import { describeMissing, missingDependencies, summarizeMissing, } from "../doctor/dependencies.js";
|
|
10
10
|
import { findFrozenBindings } from "../doctor/frozen.js";
|
|
11
|
-
import { appendEvent, readEvents, summarize } from "../doctor/ledger.js";
|
|
11
|
+
import { appendEvent, readEvents, suggestionsFrom, summarize, } from "../doctor/ledger.js";
|
|
12
12
|
import { bindingsFromDocument, countComponents, findOverrides, } from "../doctor/overrides.js";
|
|
13
13
|
import { checkableName, readRequests, verifyAndCloseRequests, } from "../doctor/requests.js";
|
|
14
14
|
import { diagnose, scanSource, siblingTokens, } from "../doctor/scan.js";
|
|
@@ -706,6 +706,9 @@ export async function doctor(opts) {
|
|
|
706
706
|
...(d.findings.some((f) => f.crossFamily)
|
|
707
707
|
? { crossFamily: d.findings.filter((f) => f.crossFamily).length }
|
|
708
708
|
: {}),
|
|
709
|
+
...(d.repeats.some((r) => r.token)
|
|
710
|
+
? { matched: suggestionsFrom(d.repeats) }
|
|
711
|
+
: {}),
|
|
709
712
|
}).catch(() => { });
|
|
710
713
|
console.log("");
|
|
711
714
|
if (opts.fix) {
|
|
@@ -796,6 +799,10 @@ export async function doctor(opts) {
|
|
|
796
799
|
coverage: d.coverage,
|
|
797
800
|
named: d.named,
|
|
798
801
|
...(crossFamily > 0 ? { crossFamily } : {}),
|
|
802
|
+
/** E os pares em si, para a plataforma reavaliar sem esperar outra medição - ver `matched`. */
|
|
803
|
+
...(d.repeats.some((r) => r.token)
|
|
804
|
+
? { matched: suggestionsFrom(d.repeats) }
|
|
805
|
+
: {}),
|
|
799
806
|
});
|
|
800
807
|
}
|
|
801
808
|
if (hasSystem && fullRun) {
|
|
@@ -922,11 +929,17 @@ export async function doctor(opts) {
|
|
|
922
929
|
for (const r of repeats) {
|
|
923
930
|
const where = `${r.count}\u00d7 in ${r.files} file${r.files === 1 ? "" : "s"}`;
|
|
924
931
|
const near = r.token ? null : nearestToken(table, r.literal);
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
932
|
+
/**
|
|
933
|
+
* COINCIDÊNCIA NÃO É RESPOSTA - ver `crossFamily` em `scan.ts`. Para aquele `kind` o
|
|
934
|
+
* sistema não tem nome; o valor mora noutra família, e dizer só a seta afirma o contrário.
|
|
935
|
+
*/
|
|
936
|
+
const named = r.crossFamily
|
|
937
|
+
? ` → no ${r.kind} named for it · the value lives as ${r.token}`
|
|
938
|
+
: r.token
|
|
939
|
+
? ` → ${r.token}`
|
|
940
|
+
: near
|
|
941
|
+
? ` → nearest is ${near.name} (${near.value})`
|
|
942
|
+
: "";
|
|
930
943
|
say(` ${r.literal.padEnd(w)} ${where}${named}`);
|
|
931
944
|
}
|
|
932
945
|
}
|
|
@@ -942,11 +955,13 @@ export async function doctor(opts) {
|
|
|
942
955
|
// A dead end with a neighbour is not a dead end. Only for lengths -
|
|
943
956
|
// "nearly the same blue" is the guess this tool must never make.
|
|
944
957
|
const near = x.token ? null : nearestToken(table, x.literal);
|
|
945
|
-
const named = x.
|
|
946
|
-
? `→ ${x.token}`
|
|
947
|
-
:
|
|
948
|
-
? `→
|
|
949
|
-
:
|
|
958
|
+
const named = x.crossFamily
|
|
959
|
+
? `→ no ${x.kind} named for it · the value lives as ${x.token}`
|
|
960
|
+
: x.token
|
|
961
|
+
? `→ ${x.token}`
|
|
962
|
+
: near
|
|
963
|
+
? `→ nearest is ${near.name} (${near.value})`
|
|
964
|
+
: "→ no token holds this value yet";
|
|
950
965
|
say(` ${String(x.line).padStart(4)} ${x.literal} ${named}`);
|
|
951
966
|
}
|
|
952
967
|
if (f.findings.length > shown.length) {
|
|
@@ -1264,8 +1279,19 @@ export async function doctor(opts) {
|
|
|
1264
1279
|
* mentir por omissão. Muda a ordem e muda quantos de cada aparecem no teto de cinco.
|
|
1265
1280
|
*/
|
|
1266
1281
|
const migrating = intent.intent === "migrate";
|
|
1267
|
-
|
|
1268
|
-
|
|
1282
|
+
/**
|
|
1283
|
+
* UMA COINCIDÊNCIA NÃO ENTRA NA LISTA DE BARATOS - ver `crossFamily` em `scan.ts`.
|
|
1284
|
+
*
|
|
1285
|
+
* A lista dos "cheap" existe para quem tem dez minutos: trocar o literal pelo token e pronto. Um
|
|
1286
|
+
* match de outra família não é isso - `--fix` o recusa, e o trabalho ali é decidir se aquele
|
|
1287
|
+
* `kind` merece um nome. Medido no repo do dono em 08/08: `2rem` era oferecido como raio porque
|
|
1288
|
+
* existe como degrau de tipo, dez vezes.
|
|
1289
|
+
*
|
|
1290
|
+
* Ele não some: vai para o grupo de quem NÃO tem nome, que é literalmente o que ele é para
|
|
1291
|
+
* aquele kind - e a linha diz onde o valor mora hoje.
|
|
1292
|
+
*/
|
|
1293
|
+
const named = d.repeats.filter((x) => x.token && !x.crossFamily);
|
|
1294
|
+
const unnamed = d.repeats.filter((x) => !x.token || x.crossFamily);
|
|
1269
1295
|
for (const r of named.slice(0, migrating ? 2 : 3)) {
|
|
1270
1296
|
plan.push({
|
|
1271
1297
|
rank: migrating ? 4 : 3,
|
|
@@ -1280,7 +1306,9 @@ export async function doctor(opts) {
|
|
|
1280
1306
|
rank: migrating ? 3 : 4,
|
|
1281
1307
|
what: near
|
|
1282
1308
|
? `${r.literal} - name it, or snap to ${near.name}`
|
|
1283
|
-
:
|
|
1309
|
+
: r.crossFamily
|
|
1310
|
+
? `${r.literal} - no ${r.kind} named for it, and the value lives as ${r.token} in another family`
|
|
1311
|
+
: `${r.literal} - the system has no name for it`,
|
|
1284
1312
|
size: `${r.files} file${r.files === 1 ? "" : "s"}`,
|
|
1285
1313
|
cheap: false,
|
|
1286
1314
|
});
|
package/dist/doctor/ci-format.js
CHANGED
|
@@ -82,7 +82,9 @@ export function compareToBaseline(d, base, now) {
|
|
|
82
82
|
/** O que a mensagem de uma anotação diz, e é a mesma frase nos dois formatos. */
|
|
83
83
|
function messageFor(f) {
|
|
84
84
|
return f.token
|
|
85
|
-
?
|
|
85
|
+
? f.crossFamily
|
|
86
|
+
? `${f.literal} is written by hand, and this project's system has no ${f.kind} named for it. The value does exist elsewhere in the system - as \`${f.token}\`, in another family - so this is a decision to make, not a swap: name a ${f.kind}, or leave it.`
|
|
87
|
+
: `${f.literal} is written by hand, and this project's system already names it: var(${f.token}). Use the token.`
|
|
86
88
|
: `${f.literal} is a ${f.kind} value written by hand, and the system has no name for it yet. Name it, or file a token request: npx synthesisui request token`;
|
|
87
89
|
}
|
|
88
90
|
/**
|
package/dist/doctor/ledger.js
CHANGED
|
@@ -27,6 +27,32 @@ import { join } from "node:path";
|
|
|
27
27
|
* same contract every log file that survives a decade has.
|
|
28
28
|
*/
|
|
29
29
|
export const LEDGER_FILE = "ledger.jsonl";
|
|
30
|
+
/**
|
|
31
|
+
* TETO, porque isto viaja e cai num campo `jsonb`.
|
|
32
|
+
*
|
|
33
|
+
* 72 no repo do dono, e a lista já vem ordenada por frequência - então o corte pega a cauda, que é
|
|
34
|
+
* onde mora o valor escrito uma vez em um arquivo. Um repo que passe disso perde a cauda e mantém
|
|
35
|
+
* inteiro o que decide alguma coisa.
|
|
36
|
+
*/
|
|
37
|
+
const MATCHED_CAP = 300;
|
|
38
|
+
/**
|
|
39
|
+
* Os pares a mandar, do agregado que o doctor já monta.
|
|
40
|
+
*
|
|
41
|
+
* Só o que casou com um token: uma sugestão que não existe não tem família para comparar, e as 714
|
|
42
|
+
* sem token do repo do dono são 90% do volume e 0% da informação. A forma é estrutural de propósito -
|
|
43
|
+
* `Diagnosis` mora em `scan.ts`, e importar de lá para cá fecharia um ciclo.
|
|
44
|
+
*/
|
|
45
|
+
export function suggestionsFrom(repeats) {
|
|
46
|
+
return repeats
|
|
47
|
+
.filter((r) => Boolean(r.token))
|
|
48
|
+
.slice(0, MATCHED_CAP)
|
|
49
|
+
.map((r) => ({
|
|
50
|
+
literal: r.literal,
|
|
51
|
+
kind: r.kind,
|
|
52
|
+
token: r.token,
|
|
53
|
+
count: r.count,
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
30
56
|
const ledgerPath = (root) => join(root, "_synthesisui", LEDGER_FILE);
|
|
31
57
|
/** Keep the file from growing forever: past ~1MB, keep the newest half. A
|
|
32
58
|
* trend needs recent history, not an archive. */
|
package/dist/doctor/scan.js
CHANGED
|
@@ -489,6 +489,7 @@ export function diagnose(files) {
|
|
|
489
489
|
token: f.token,
|
|
490
490
|
count: 1,
|
|
491
491
|
files: new Set([f.file]),
|
|
492
|
+
...(f.crossFamily ? { crossFamily: true } : {}),
|
|
492
493
|
});
|
|
493
494
|
}
|
|
494
495
|
}
|
|
@@ -499,6 +500,7 @@ export function diagnose(files) {
|
|
|
499
500
|
token: v.token,
|
|
500
501
|
count: v.count,
|
|
501
502
|
files: v.files.size,
|
|
503
|
+
...(v.crossFamily ? { crossFamily: true } : {}),
|
|
502
504
|
}))
|
|
503
505
|
.filter((r) => r.count > 1)
|
|
504
506
|
.sort((a, b) => b.count - a.count);
|
package/dist/repo-state.js
CHANGED
|
@@ -53,6 +53,9 @@ export async function repoStateOf(projectRoot, slug, cli) {
|
|
|
53
53
|
...(typeof doctor?.crossFamily === "number"
|
|
54
54
|
? { crossFamily: doctor.crossFamily }
|
|
55
55
|
: {}),
|
|
56
|
+
...(doctor?.matched && doctor.matched.length > 0
|
|
57
|
+
? { matched: doctor.matched }
|
|
58
|
+
: {}),
|
|
56
59
|
...(typeof lock?.fetchedAt === "string"
|
|
57
60
|
? { installedAt: lock.fetchedAt }
|
|
58
61
|
: {}),
|
package/package.json
CHANGED