synthesisui 0.16.176 → 0.16.178
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 +6 -2
- package/dist/commands/add.js +2 -0
- package/dist/commands/align.js +7 -2
- package/dist/commands/connect.js +13 -3
- package/dist/commands/sync.js +6 -1
- package/dist/doctor/ledger.js +49 -0
- package/package.json +1 -1
package/dist/claude-md.js
CHANGED
|
@@ -412,6 +412,7 @@ export async function syncClaudeMd(projectRoot) {
|
|
|
412
412
|
const installed = await readInstalled(projectRoot);
|
|
413
413
|
const region = await renderRegion(projectRoot, installed);
|
|
414
414
|
let createdAny = false;
|
|
415
|
+
const changed = [];
|
|
415
416
|
for (const home of HOMES) {
|
|
416
417
|
const path = join(projectRoot, home.path);
|
|
417
418
|
let existing = null;
|
|
@@ -435,6 +436,7 @@ export async function syncClaudeMd(projectRoot) {
|
|
|
435
436
|
await mkdir(dirname(path), { recursive: true }).catch(() => { });
|
|
436
437
|
await writeFile(path, `${home.frontmatter ?? ""}${region}\n`, "utf8");
|
|
437
438
|
createdAny = true;
|
|
439
|
+
changed.push(home.path);
|
|
438
440
|
continue;
|
|
439
441
|
}
|
|
440
442
|
const startIdx = existing.indexOf(START);
|
|
@@ -450,10 +452,12 @@ export async function syncClaudeMd(projectRoot) {
|
|
|
450
452
|
const sep = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
451
453
|
next = `${existing}${sep}${region}\n`;
|
|
452
454
|
}
|
|
453
|
-
if (next !== existing)
|
|
455
|
+
if (next !== existing) {
|
|
454
456
|
await writeFile(path, next, "utf8");
|
|
457
|
+
changed.push(home.path);
|
|
458
|
+
}
|
|
455
459
|
}
|
|
456
|
-
return { created: createdAny, count: installed.length };
|
|
460
|
+
return { created: createdAny, count: installed.length, changed };
|
|
457
461
|
}
|
|
458
462
|
/**
|
|
459
463
|
* Onde o bloco JÁ está, para o `connect` poder dizer isso em vez de ficar calado.
|
package/dist/commands/add.js
CHANGED
|
@@ -39,6 +39,8 @@ async function writeGovernanceIgnore(projectRoot) {
|
|
|
39
39
|
"# both are rewritten in full on every run and would conflict on every merge.\n" +
|
|
40
40
|
"census.json\n" +
|
|
41
41
|
"ledger.jsonl\n" +
|
|
42
|
+
/** O cursor de envio descreve ESTE clone, não o repositório - ver `markSent`. */
|
|
43
|
+
".ledger-sent\n" +
|
|
42
44
|
"not-expressed.md\n", "utf8");
|
|
43
45
|
}
|
|
44
46
|
/**
|
package/dist/commands/align.js
CHANGED
|
@@ -2,7 +2,7 @@ import { readdir, readFile } from "node:fs/promises";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { readToken, resolveRegistry } from "../config.js";
|
|
5
|
-
import {
|
|
5
|
+
import { unsentEvents } from "../doctor/ledger.js";
|
|
6
6
|
import { measuredScope } from "../measured-scope.js";
|
|
7
7
|
import { READER } from "../reader-version.js";
|
|
8
8
|
/**
|
|
@@ -124,7 +124,12 @@ opts = {}) {
|
|
|
124
124
|
*/
|
|
125
125
|
run: "npx synthesisui sync",
|
|
126
126
|
});
|
|
127
|
-
|
|
127
|
+
/**
|
|
128
|
+
* SÓ O QUE NÃO SUBIU - ver `unsentEvents`. Isto contava o arquivo inteiro, e como o ledger é
|
|
129
|
+
* append-only e o `sync` manda tudo (a plataforma deduplica), a linha nunca mais saía da tela e o
|
|
130
|
+
* número só crescia.
|
|
131
|
+
*/
|
|
132
|
+
const events = await unsentEvents(root).catch(() => []);
|
|
128
133
|
if (events.length > 0)
|
|
129
134
|
out.push({
|
|
130
135
|
says: `${events.length} checked write${events.length === 1 ? "" : "s"} recorded here and not sent - the platform is scoring this repo on older evidence.`,
|
package/dist/commands/connect.js
CHANGED
|
@@ -173,7 +173,7 @@ export async function connect(opts) {
|
|
|
173
173
|
const wired = await wireAgent(root, opts.version, want);
|
|
174
174
|
// The block reads the settings we just wrote, so it must be regenerated
|
|
175
175
|
// after them, not before.
|
|
176
|
-
await syncClaudeMd(root);
|
|
176
|
+
const contract = await syncClaudeMd(root);
|
|
177
177
|
console.log(section("Connected"));
|
|
178
178
|
/**
|
|
179
179
|
* O QUE ESTE CLI REESCREVEU NA PASTA DO SISTEMA - dito primeiro, porque é o que a pessoa não sabia
|
|
@@ -231,8 +231,18 @@ export async function connect(opts) {
|
|
|
231
231
|
* qual ferramenta ela usa. Dizer os nomes é o que faz um time descobrir que a governança já chegou
|
|
232
232
|
* no editor dele: até 05/08 ela só alcançava quem usa Claude Code, e ninguém tinha como saber.
|
|
233
233
|
*/
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
/**
|
|
235
|
+
* `✓` SÓ PARA O QUE MUDOU - ver `syncClaudeMd.changed`. Esta linha era a única do bloco que
|
|
236
|
+
* marcava mudança sempre, e um `connect` seguido dizia "rewritten" sobre um arquivo intocado.
|
|
237
|
+
*/
|
|
238
|
+
for (const home of await blockHomes(root)) {
|
|
239
|
+
const moved = contract.changed.includes(home);
|
|
240
|
+
console.log(body(`${moved ? "✓" : "·"} ${home.padEnd(22)} ${moved
|
|
241
|
+
? home === "CLAUDE.md"
|
|
242
|
+
? "rewritten for what is installed"
|
|
243
|
+
: "the same rules, where this agent reads them"
|
|
244
|
+
: "already says what is installed"}`));
|
|
245
|
+
}
|
|
236
246
|
/**
|
|
237
247
|
* The fourth layer, and the one that had no installer at all: the import
|
|
238
248
|
* skill existed only in our own repo, so the only way to get it was to clone
|
package/dist/commands/sync.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import { readToken, resolveRegistry } from "../config.js";
|
|
4
|
-
import { readEvents } from "../doctor/ledger.js";
|
|
4
|
+
import { markSent, readEvents } from "../doctor/ledger.js";
|
|
5
5
|
import { checkableName, closeRequest, readRequests, verifyAndCloseRequests, } from "../doctor/requests.js";
|
|
6
6
|
import { measuredScope, rememberScope } from "../measured-scope.js";
|
|
7
7
|
import { body, paint, section, snippet } from "../output.js";
|
|
@@ -114,6 +114,11 @@ export async function sync(opts) {
|
|
|
114
114
|
console.log(body(err.message ?? `The registry answered ${res.status}.`));
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* O QUE SUBIU, ANOTADO - senão o `align` continua pedindo o envio do que acabou de ser enviado.
|
|
119
|
+
* Depois da resposta OK, e nunca antes: marcar um envio que falhou perderia os eventos de vez.
|
|
120
|
+
*/
|
|
121
|
+
await markSent(root, events);
|
|
117
122
|
const out = (await res.json());
|
|
118
123
|
console.log(section("Sync"));
|
|
119
124
|
console.log(body(`${out.eventsReceived} checks sent, ${out.eventsNew} new. ${out.requestsNow} open request${out.requestsNow === 1 ? "" : "s"}.`));
|
package/dist/doctor/ledger.js
CHANGED
|
@@ -46,6 +46,55 @@ export async function appendEvent(root, event) {
|
|
|
46
46
|
// is a ledger that gets the hook uninstalled.
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* ATÉ ONDE ESTE REPO JÁ MANDOU - e a ausência disto fazia o `align` mentir para sempre.
|
|
51
|
+
*
|
|
52
|
+
* O ledger é APPEND-ONLY e o `sync` manda o arquivo inteiro; a plataforma deduplica (em 07/08 uma
|
|
53
|
+
* rodada reportou "6 checks sent, 1 new"). Só que o `align` contava TODAS as linhas e dizia "6
|
|
54
|
+
* checked writes recorded here and not sent" - sobre cinco que tinham subido minutos antes. O número
|
|
55
|
+
* só crescia, então aquela linha nunca mais sairia da tela, e um aviso permanente é um aviso que a
|
|
56
|
+
* pessoa aprende a pular (dono, 07/08: *"quer apostar que você vai achar algo errado?"*).
|
|
57
|
+
*
|
|
58
|
+
* A CONTAGEM E A HORA, as duas: a contagem responde sozinha enquanto o arquivo só cresce, e a hora
|
|
59
|
+
* dá como perceber que ele foi trocado por outro - aí a contagem antiga não vale mais nada.
|
|
60
|
+
*/
|
|
61
|
+
const SENT_FILE = ".ledger-sent";
|
|
62
|
+
const sentPath = (root) => join(root, "_synthesisui", SENT_FILE);
|
|
63
|
+
export async function readSent(root) {
|
|
64
|
+
const raw = await readFile(sentPath(root), "utf8").catch(() => "");
|
|
65
|
+
if (!raw)
|
|
66
|
+
return { count: 0 };
|
|
67
|
+
try {
|
|
68
|
+
const v = JSON.parse(raw);
|
|
69
|
+
return {
|
|
70
|
+
count: typeof v.count === "number" && v.count >= 0 ? v.count : 0,
|
|
71
|
+
...(typeof v.at === "string" ? { at: v.at } : {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return { count: 0 };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export async function markSent(root, events) {
|
|
79
|
+
const last = events[events.length - 1]?.at;
|
|
80
|
+
await writeFile(sentPath(root), `${JSON.stringify({ count: events.length, ...(last ? { at: last } : {}) })}\n`, "utf8").catch(() => {
|
|
81
|
+
/** O registro nunca pode custar o envio: o pior caso é o aviso reaparecer uma vez. */
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Os eventos que este repo ainda não mandou.
|
|
86
|
+
*
|
|
87
|
+
* Se a contagem gravada é maior que o arquivo, alguém o trocou ou apagou - e aí a marca não descreve
|
|
88
|
+
* mais este arquivo. Contar tudo de novo é a leitura honesta: um envio a mais custa nada, e a
|
|
89
|
+
* plataforma deduplica.
|
|
90
|
+
*/
|
|
91
|
+
export async function unsentEvents(root) {
|
|
92
|
+
const all = await readEvents(root);
|
|
93
|
+
const { count } = await readSent(root);
|
|
94
|
+
if (count <= 0 || count > all.length)
|
|
95
|
+
return all;
|
|
96
|
+
return all.slice(count);
|
|
97
|
+
}
|
|
49
98
|
export async function readEvents(root) {
|
|
50
99
|
const raw = await readFile(ledgerPath(root), "utf8").catch(() => "");
|
|
51
100
|
if (!raw)
|
package/package.json
CHANGED