brainblast 0.6.4 → 0.7.0

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.
@@ -0,0 +1,14 @@
1
+ import {
2
+ batchScan,
3
+ parseMintList,
4
+ renderBatchText
5
+ } from "./chunk-QC27GNQ7.js";
6
+ import "./chunk-FQA5BYWW.js";
7
+ import "./chunk-VI2JBH2T.js";
8
+ import "./chunk-2XJORJPQ.js";
9
+ import "./chunk-3RG5ZIWI.js";
10
+ export {
11
+ batchScan,
12
+ parseMintList,
13
+ renderBatchText
14
+ };
@@ -0,0 +1,77 @@
1
+ // src/trustGraph/render.ts
2
+ function renderAuthority(p) {
3
+ const a = p.upgradeAuthority;
4
+ switch (a.kind) {
5
+ case "renounced":
6
+ return "\u{1F512} **Renounced** \u2014 program is frozen; no key can upgrade it.";
7
+ case "single-key":
8
+ return `\u26A0\uFE0F **Single key** \`${a.address}\` \u2014 one private key can replace this program at any time.`;
9
+ case "multisig":
10
+ return `\u{1F510} **Multisig** \`${a.address}\` \u2014 a threshold of signers can upgrade.`;
11
+ case "dao":
12
+ return `\u{1F3DB} **DAO** \`${a.address}\` \u2014 governance program controls upgrades.`;
13
+ case "unknown":
14
+ return a.address ? `\u2753 **Unclassified authority** \`${a.address}\` \u2014 needs research to confirm single-key vs multisig/DAO.` : "\u2753 **Unknown** \u2014 could not determine upgrade authority.";
15
+ }
16
+ }
17
+ function renderVerified(p) {
18
+ const v = p.verifiedBuild;
19
+ switch (v.state) {
20
+ case "verified":
21
+ return `\u2705 Verified build${v.commit ? ` @ \`${v.commit.slice(0, 12)}\`` : ""} \u2014 [registry](${v.registryUrl})`;
22
+ case "unverified":
23
+ return "\u274C Unverified \u2014 on-chain bytecode does not match any source we trust.";
24
+ case "unknown":
25
+ return "\u2753 Verified-build status not checked.";
26
+ }
27
+ }
28
+ function renderAudits(p) {
29
+ if (!p.audits.length) return "_No audits on file._";
30
+ return p.audits.map((a) => `- ${a.firm} (${a.date}) \u2014 [report](${a.reportUrl})${a.auditedCommit ? ` @ \`${a.auditedCommit.slice(0, 12)}\`` : ""}`).join("\n");
31
+ }
32
+ function renderParity(p) {
33
+ const { mainnet, devnet, testnet, notes } = p.parity;
34
+ const cells = [`mainnet=\`${mainnet}\``, `devnet=\`${devnet}\``];
35
+ if (testnet) cells.push(`testnet=\`${testnet}\``);
36
+ return cells.join(" \xB7 ") + (notes ? `
37
+ _${notes}_` : "");
38
+ }
39
+ function renderProgram(p) {
40
+ return [
41
+ `### ${p.name}`,
42
+ "",
43
+ `\`${p.programId}\`${p.kind ? ` \xB7 kind: \`${p.kind}\`` : ""}`,
44
+ "",
45
+ `- **Upgrade authority:** ${renderAuthority(p)}`,
46
+ `- **Verified build:** ${renderVerified(p)}`,
47
+ `- **Parity:** ${renderParity(p)}`,
48
+ `- **Audits:**
49
+ ${renderAudits(p).split("\n").map((l) => " " + l).join("\n")}`,
50
+ p.invokes && p.invokes.length ? `- **Invokes (CPI):** ${p.invokes.map((id) => `\`${id}\``).join(", ")}` : ""
51
+ ].filter(Boolean).join("\n");
52
+ }
53
+ function renderTrustGraphMd(g) {
54
+ const head = [
55
+ "# Trust Graph",
56
+ "",
57
+ `_Generated ${g.generatedAt}._`,
58
+ "",
59
+ "Every program your code transitively invokes, with the authority that controls it, the build-verification status, and the audits we found.",
60
+ ""
61
+ ].join("\n");
62
+ const body = g.programs.map(renderProgram).join("\n\n---\n\n");
63
+ const tail = g.unresolved.length ? [
64
+ "",
65
+ "---",
66
+ "",
67
+ "## Unresolved",
68
+ "",
69
+ ...g.unresolved.map((u) => `- \`${u.programId}\` \u2014 ${u.reason}`)
70
+ ].join("\n") : "";
71
+ return head + body + tail + "\n";
72
+ }
73
+
74
+ export {
75
+ renderProgram,
76
+ renderTrustGraphMd
77
+ };
@@ -7,393 +7,7 @@ import {
7
7
  loadPack,
8
8
  resolveRules,
9
9
  walk
10
- } from "./chunk-2Y6UILTZ.js";
11
-
12
- // src/trustGraph/directory.ts
13
- import { readFileSync, existsSync } from "fs";
14
- import { fileURLToPath } from "url";
15
- import { join } from "path";
16
- import { parse } from "yaml";
17
- var cache = null;
18
- function bundledPath() {
19
- const here = fileURLToPath(new URL(".", import.meta.url));
20
- const candidates = [
21
- join(here, "programs", "directory.yaml"),
22
- // dist/programs/directory.yaml
23
- join(here, "..", "..", "programs", "directory.yaml"),
24
- // src/../../programs/
25
- join(here, "..", "programs", "directory.yaml")
26
- // fallback
27
- ];
28
- for (const c of candidates) {
29
- if (existsSync(c)) return c;
30
- }
31
- return candidates[0];
32
- }
33
- function loadDirectory(path = bundledPath()) {
34
- if (cache && path === bundledPath()) return cache;
35
- const raw = parse(readFileSync(path, "utf8"));
36
- if (!raw || !Array.isArray(raw.programs)) {
37
- throw new Error(`invalid program directory at ${path}: missing 'programs' array`);
38
- }
39
- const m = /* @__PURE__ */ new Map();
40
- for (const p of raw.programs) {
41
- if (!p.programId || !p.name) throw new Error(`directory entry missing programId/name: ${JSON.stringify(p)}`);
42
- if (m.has(p.programId)) throw new Error(`directory has duplicate programId ${p.programId}`);
43
- m.set(p.programId, { ...p, provenance: { ...p.provenance ?? {}, directoryFile: path } });
44
- }
45
- if (path === bundledPath()) cache = m;
46
- return m;
47
- }
48
-
49
- // src/trustGraph/base58.ts
50
- var ALPHA = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
51
- var MAP = {};
52
- for (let i = 0; i < ALPHA.length; i++) MAP[ALPHA[i]] = i;
53
- function base58Encode(bytes) {
54
- let zeros = 0;
55
- while (zeros < bytes.length && bytes[zeros] === 0) zeros++;
56
- const buf = Array.from(bytes);
57
- const out = [];
58
- let start = zeros;
59
- while (start < buf.length) {
60
- let rem = 0;
61
- for (let i = start; i < buf.length; i++) {
62
- const acc = rem * 256 + buf[i];
63
- buf[i] = Math.floor(acc / 58);
64
- rem = acc % 58;
65
- }
66
- out.push(rem);
67
- if (buf[start] === 0) start++;
68
- }
69
- let s = "";
70
- for (let i = 0; i < zeros; i++) s += "1";
71
- for (let i = out.length - 1; i >= 0; i--) s += ALPHA[out[i]];
72
- return s;
73
- }
74
- function base58Decode(s) {
75
- let zeros = 0;
76
- while (zeros < s.length && s[zeros] === "1") zeros++;
77
- const buf = [];
78
- for (let i = zeros; i < s.length; i++) {
79
- const v = MAP[s[i]];
80
- if (v === void 0) throw new Error(`base58: invalid char '${s[i]}' at ${i}`);
81
- let carry = v;
82
- for (let j = 0; j < buf.length; j++) {
83
- const acc = buf[j] * 58 + carry;
84
- buf[j] = acc & 255;
85
- carry = acc >>> 8;
86
- }
87
- while (carry > 0) {
88
- buf.push(carry & 255);
89
- carry >>>= 8;
90
- }
91
- }
92
- const out = new Uint8Array(zeros + buf.length);
93
- for (let i = 0; i < buf.length; i++) out[zeros + buf.length - 1 - i] = buf[i];
94
- return out;
95
- }
96
- function isValidSolanaAddress(s) {
97
- if (typeof s !== "string" || s.length < 32 || s.length > 44) return false;
98
- try {
99
- return base58Decode(s).length === 32;
100
- } catch {
101
- return false;
102
- }
103
- }
104
-
105
- // src/trustGraph/programCache.ts
106
- import { readFileSync as readFileSync2, writeFileSync, mkdirSync, existsSync as existsSync2 } from "fs";
107
- import { join as join2, dirname } from "path";
108
- import { homedir } from "os";
109
- var DEFAULT_TTL_HOURS = 168;
110
- var SCHEMA_VERSION = "1.0";
111
- function defaultCachePath() {
112
- const envOverride = process.env["BRAINBLAST_CACHE_PATH"];
113
- return envOverride ?? join2(homedir(), ".brainblast", "program-cache.json");
114
- }
115
- function emptyCache() {
116
- return { schemaVersion: SCHEMA_VERSION, entries: {} };
117
- }
118
- function loadProgramCache(cachePath) {
119
- const path = cachePath ?? defaultCachePath();
120
- if (!existsSync2(path)) return emptyCache();
121
- try {
122
- const raw = JSON.parse(readFileSync2(path, "utf8"));
123
- if (raw?.schemaVersion !== SCHEMA_VERSION) {
124
- return emptyCache();
125
- }
126
- if (!raw.entries || typeof raw.entries !== "object") return emptyCache();
127
- return { schemaVersion: SCHEMA_VERSION, entries: raw.entries };
128
- } catch {
129
- return emptyCache();
130
- }
131
- }
132
- function saveProgramCache(cache2, cachePath) {
133
- const path = cachePath ?? defaultCachePath();
134
- mkdirSync(dirname(path), { recursive: true });
135
- writeFileSync(path, JSON.stringify(cache2, null, 2), "utf8");
136
- }
137
- function getCacheEntry(cache2, programId, ttlHoursOverride) {
138
- const entry = cache2.entries[programId];
139
- if (!entry) return null;
140
- if (isEntryExpired(entry, ttlHoursOverride)) return null;
141
- return entry.program;
142
- }
143
- function putCacheEntry(cache2, programId, program, sourceRun, ttlHours = DEFAULT_TTL_HOURS) {
144
- cache2.entries[programId] = {
145
- program,
146
- cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
147
- sourceRun,
148
- ttlHours
149
- };
150
- return cache2;
151
- }
152
- function getCacheEntryMeta(cache2, programId) {
153
- return cache2.entries[programId] ?? null;
154
- }
155
- function isEntryExpired(entry, ttlHoursOverride) {
156
- const ttl = ttlHoursOverride ?? entry.ttlHours ?? DEFAULT_TTL_HOURS;
157
- if (ttl <= 0) return true;
158
- const cachedMs = Date.parse(entry.cachedAt);
159
- if (Number.isNaN(cachedMs)) return true;
160
- const ageMs = Date.now() - cachedMs;
161
- return ageMs >= ttl * 36e5;
162
- }
163
- function cacheSize(cache2, ttlHoursOverride) {
164
- return Object.values(cache2.entries).filter((e) => !isEntryExpired(e, ttlHoursOverride)).length;
165
- }
166
-
167
- // src/trustGraph/rpc.ts
168
- var BPF_UPGRADEABLE_LOADER = "BPFLoaderUpgradeab1e11111111111111111111111";
169
- var BPF_LOADER_2 = "BPFLoader2111111111111111111111111111111111";
170
- var NATIVE_LOADER = "NativeLoader1111111111111111111111111111111";
171
- var DEFAULT_RPC = "https://api.mainnet-beta.solana.com";
172
- async function rpc(method, params, opts) {
173
- const url = opts.rpcUrl ?? DEFAULT_RPC;
174
- const fetchImpl = opts.fetchImpl ?? fetch;
175
- const ac = new AbortController();
176
- const t = setTimeout(() => ac.abort(), opts.timeoutMs ?? 1e4);
177
- try {
178
- const res = await fetchImpl(url, {
179
- method: "POST",
180
- headers: { "content-type": "application/json" },
181
- body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
182
- signal: ac.signal
183
- });
184
- if (!res.ok) throw new Error(`rpc ${method}: HTTP ${res.status}`);
185
- const body = await res.json();
186
- if (body.error) throw new Error(`rpc ${method}: ${body.error.message}`);
187
- if (body.result === void 0) throw new Error(`rpc ${method}: empty result`);
188
- return body.result;
189
- } finally {
190
- clearTimeout(t);
191
- }
192
- }
193
- async function getAccountInfo(address, opts = {}) {
194
- if (!isValidSolanaAddress(address)) throw new Error(`invalid Solana address: ${address}`);
195
- const result = await rpc(
196
- "getAccountInfo",
197
- [address, { encoding: "base64", commitment: "confirmed" }],
198
- opts
199
- );
200
- if (!result || !result.value) return null;
201
- const v = result.value;
202
- const [b64] = v.data;
203
- return {
204
- owner: v.owner,
205
- data: Buffer.from(b64, "base64"),
206
- executable: v.executable,
207
- lamports: v.lamports
208
- };
209
- }
210
- async function probeUpgradeAuthority(programId, opts = {}) {
211
- const acct = await getAccountInfo(programId, opts);
212
- if (!acct) {
213
- return {
214
- kind: "unknown",
215
- address: null,
216
- source: "rpc",
217
- checkedAt: (/* @__PURE__ */ new Date()).toISOString()
218
- };
219
- }
220
- if (acct.owner === BPF_LOADER_2 || acct.owner === NATIVE_LOADER) {
221
- return {
222
- kind: "renounced",
223
- address: null,
224
- source: "rpc",
225
- checkedAt: (/* @__PURE__ */ new Date()).toISOString()
226
- };
227
- }
228
- if (acct.owner !== BPF_UPGRADEABLE_LOADER) {
229
- throw new Error(
230
- `program ${programId} is owned by ${acct.owner}, not a known loader; not a deployed program?`
231
- );
232
- }
233
- if (acct.data.length < 36) throw new Error(`program account too small: ${acct.data.length}`);
234
- const tag = acct.data[0] | acct.data[1] << 8 | acct.data[2] << 16 | acct.data[3] << 24;
235
- if (tag !== 2) throw new Error(`expected Program (tag=2) state, got tag=${tag}`);
236
- const programDataAddr = base58Encode(acct.data.subarray(4, 36));
237
- const pd = await getAccountInfo(programDataAddr, opts);
238
- if (!pd) {
239
- throw new Error(`program ${programId} ProgramData ${programDataAddr} not found`);
240
- }
241
- if (pd.data.length < 45) throw new Error(`ProgramData account too small: ${pd.data.length}`);
242
- const pdTag = pd.data[0] | pd.data[1] << 8 | pd.data[2] << 16 | pd.data[3] << 24;
243
- if (pdTag !== 3) throw new Error(`expected ProgramData (tag=3), got tag=${pdTag}`);
244
- const optionTag = pd.data[12];
245
- const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
246
- if (optionTag === 0) {
247
- return { kind: "renounced", address: null, source: "rpc", checkedAt };
248
- }
249
- if (optionTag !== 1) throw new Error(`unexpected Option tag in ProgramData: ${optionTag}`);
250
- const authority = base58Encode(pd.data.subarray(13, 45));
251
- return { kind: "unknown", address: authority, source: "rpc", checkedAt };
252
- }
253
-
254
- // src/trustGraph/build.ts
255
- async function buildTrustGraph(programIds, opts = {}) {
256
- const dir = loadDirectory(opts.directoryPath);
257
- const programs = [];
258
- const unresolved = [];
259
- const cacheEnabled = opts.cachePath !== null;
260
- const cachePathArg = opts.cachePath === null ? void 0 : opts.cachePath;
261
- const cache2 = cacheEnabled ? loadProgramCache(cachePathArg) : null;
262
- const newFromRpc = [];
263
- const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T]/g, "").slice(0, 14);
264
- const seen = /* @__PURE__ */ new Set();
265
- const ordered = programIds.filter((id) => seen.has(id) ? false : (seen.add(id), true));
266
- for (const id of ordered) {
267
- const directoryHit = dir.get(id);
268
- if (directoryHit) {
269
- programs.push(directoryHit);
270
- continue;
271
- }
272
- if (cache2) {
273
- const cached = getCacheEntry(cache2, id);
274
- if (cached) {
275
- const meta = getCacheEntryMeta(cache2, id);
276
- programs.push({
277
- ...cached,
278
- provenance: {
279
- ...cached.provenance ?? {},
280
- notes: [
281
- cached.provenance?.notes,
282
- `cache-hit: cachedAt=${meta.cachedAt} sourceRun=${meta.sourceRun}`
283
- ].filter(Boolean).join("; ")
284
- }
285
- });
286
- continue;
287
- }
288
- }
289
- if (opts.probeRpc === false) {
290
- unresolved.push({
291
- programId: id,
292
- reason: "not_in_directory_or_cache_and_rpc_disabled"
293
- });
294
- continue;
295
- }
296
- let authority;
297
- try {
298
- authority = await probeUpgradeAuthority(id, opts);
299
- } catch (e) {
300
- unresolved.push({ programId: id, reason: `rpc_error: ${e?.message ?? String(e)}` });
301
- continue;
302
- }
303
- const probed = {
304
- programId: id,
305
- name: `Unknown program (${id.slice(0, 8)}\u2026)`,
306
- kind: "app",
307
- upgradeAuthority: authority,
308
- verifiedBuild: { state: "unknown" },
309
- audits: [],
310
- parity: { mainnet: "unknown", devnet: "unknown" },
311
- provenance: { rpcUrl: opts.rpcUrl, notes: "live-probed; not in curated directory" }
312
- };
313
- programs.push(probed);
314
- newFromRpc.push(id);
315
- if (cache2) {
316
- putCacheEntry(cache2, id, probed, runId);
317
- }
318
- }
319
- if (cache2 && newFromRpc.length > 0) {
320
- saveProgramCache(cache2, cachePathArg);
321
- }
322
- return { programs, unresolved, generatedAt: (/* @__PURE__ */ new Date()).toISOString() };
323
- }
324
-
325
- // src/trustGraph/render.ts
326
- function renderAuthority(p) {
327
- const a = p.upgradeAuthority;
328
- switch (a.kind) {
329
- case "renounced":
330
- return "\u{1F512} **Renounced** \u2014 program is frozen; no key can upgrade it.";
331
- case "single-key":
332
- return `\u26A0\uFE0F **Single key** \`${a.address}\` \u2014 one private key can replace this program at any time.`;
333
- case "multisig":
334
- return `\u{1F510} **Multisig** \`${a.address}\` \u2014 a threshold of signers can upgrade.`;
335
- case "dao":
336
- return `\u{1F3DB} **DAO** \`${a.address}\` \u2014 governance program controls upgrades.`;
337
- case "unknown":
338
- return a.address ? `\u2753 **Unclassified authority** \`${a.address}\` \u2014 needs research to confirm single-key vs multisig/DAO.` : "\u2753 **Unknown** \u2014 could not determine upgrade authority.";
339
- }
340
- }
341
- function renderVerified(p) {
342
- const v = p.verifiedBuild;
343
- switch (v.state) {
344
- case "verified":
345
- return `\u2705 Verified build${v.commit ? ` @ \`${v.commit.slice(0, 12)}\`` : ""} \u2014 [registry](${v.registryUrl})`;
346
- case "unverified":
347
- return "\u274C Unverified \u2014 on-chain bytecode does not match any source we trust.";
348
- case "unknown":
349
- return "\u2753 Verified-build status not checked.";
350
- }
351
- }
352
- function renderAudits(p) {
353
- if (!p.audits.length) return "_No audits on file._";
354
- return p.audits.map((a) => `- ${a.firm} (${a.date}) \u2014 [report](${a.reportUrl})${a.auditedCommit ? ` @ \`${a.auditedCommit.slice(0, 12)}\`` : ""}`).join("\n");
355
- }
356
- function renderParity(p) {
357
- const { mainnet, devnet, testnet, notes } = p.parity;
358
- const cells = [`mainnet=\`${mainnet}\``, `devnet=\`${devnet}\``];
359
- if (testnet) cells.push(`testnet=\`${testnet}\``);
360
- return cells.join(" \xB7 ") + (notes ? `
361
- _${notes}_` : "");
362
- }
363
- function renderProgram(p) {
364
- return [
365
- `### ${p.name}`,
366
- "",
367
- `\`${p.programId}\`${p.kind ? ` \xB7 kind: \`${p.kind}\`` : ""}`,
368
- "",
369
- `- **Upgrade authority:** ${renderAuthority(p)}`,
370
- `- **Verified build:** ${renderVerified(p)}`,
371
- `- **Parity:** ${renderParity(p)}`,
372
- `- **Audits:**
373
- ${renderAudits(p).split("\n").map((l) => " " + l).join("\n")}`,
374
- p.invokes && p.invokes.length ? `- **Invokes (CPI):** ${p.invokes.map((id) => `\`${id}\``).join(", ")}` : ""
375
- ].filter(Boolean).join("\n");
376
- }
377
- function renderTrustGraphMd(g) {
378
- const head = [
379
- "# Trust Graph",
380
- "",
381
- `_Generated ${g.generatedAt}._`,
382
- "",
383
- "Every program your code transitively invokes, with the authority that controls it, the build-verification status, and the audits we found.",
384
- ""
385
- ].join("\n");
386
- const body = g.programs.map(renderProgram).join("\n\n---\n\n");
387
- const tail = g.unresolved.length ? [
388
- "",
389
- "---",
390
- "",
391
- "## Unresolved",
392
- "",
393
- ...g.unresolved.map((u) => `- \`${u.programId}\` \u2014 ${u.reason}`)
394
- ].join("\n") : "";
395
- return head + body + tail + "\n";
396
- }
10
+ } from "./chunk-CRYFCQYM.js";
397
11
 
398
12
  // src/costAnalysis.ts
399
13
  import { Project, SyntaxKind } from "ts-morph";
@@ -696,7 +310,7 @@ function startWatch(targetDir, opts = {}) {
696
310
  }
697
311
 
698
312
  // src/fixers/applyDiff.ts
699
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
313
+ import { readFileSync, writeFileSync } from "fs";
700
314
  function parseDiff(diff) {
701
315
  const lines = diff.split("\n");
702
316
  const fileLine = lines.find((l) => l.startsWith("+++ b"));
@@ -713,21 +327,21 @@ function parseDiff(diff) {
713
327
  }
714
328
  function applyDiffToFile(diff) {
715
329
  const { filePath, oldStart, oldCount, newLines } = parseDiff(diff);
716
- const content = readFileSync3(filePath, "utf8");
330
+ const content = readFileSync(filePath, "utf8");
717
331
  const fileLines = content.split("\n");
718
332
  const removedLines = diff.split("\n").filter((l) => l.startsWith("-") && !l.startsWith("---")).map((l) => l.slice(1));
719
333
  const actual = fileLines.slice(oldStart - 1, oldStart - 1 + oldCount);
720
334
  if (JSON.stringify(actual) !== JSON.stringify(removedLines)) return false;
721
335
  fileLines.splice(oldStart - 1, oldCount, ...newLines);
722
- writeFileSync2(filePath, fileLines.join("\n"));
336
+ writeFileSync(filePath, fileLines.join("\n"));
723
337
  return true;
724
338
  }
725
339
 
726
340
  // src/pack.ts
727
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
728
- import { join as join3 } from "path";
341
+ import { existsSync, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
342
+ import { join } from "path";
729
343
  function initPack(dir, opts) {
730
- if (existsSync3(join3(dir, PACK_MANIFEST_FILE))) {
344
+ if (existsSync(join(dir, PACK_MANIFEST_FILE))) {
731
345
  throw new Error(`${dir} already contains a ${PACK_MANIFEST_FILE}`);
732
346
  }
733
347
  const manifest = {
@@ -737,9 +351,9 @@ function initPack(dir, opts) {
737
351
  author: opts.author ?? "unknown",
738
352
  ...opts.description ? { description: opts.description } : {}
739
353
  };
740
- mkdirSync2(dir, { recursive: true });
741
- mkdirSync2(join3(dir, "rules"), { recursive: true });
742
- mkdirSync2(join3(dir, "fixtures"), { recursive: true });
354
+ mkdirSync(dir, { recursive: true });
355
+ mkdirSync(join(dir, "rules"), { recursive: true });
356
+ mkdirSync(join(dir, "fixtures"), { recursive: true });
743
357
  const manifestYaml = [
744
358
  `id: ${manifest.id}`,
745
359
  `name: ${manifest.name}`,
@@ -748,18 +362,18 @@ function initPack(dir, opts) {
748
362
  ...manifest.description ? [`description: ${manifest.description}`] : [],
749
363
  ""
750
364
  ].join("\n");
751
- const manifestFile = join3(dir, PACK_MANIFEST_FILE);
752
- writeFileSync3(manifestFile, manifestYaml, "utf8");
365
+ const manifestFile = join(dir, PACK_MANIFEST_FILE);
366
+ writeFileSync2(manifestFile, manifestYaml, "utf8");
753
367
  return manifestFile;
754
368
  }
755
369
  function validatePack(dir) {
756
370
  const { manifest, rules } = loadPack(dir);
757
- const fixturesRoot = join3(dir, "fixtures");
371
+ const fixturesRoot = join(dir, "fixtures");
758
372
  const ruleResults = rules.map((rule) => {
759
- const ruleFixturesDir = join3(fixturesRoot, rule.id);
760
- const vulnerableDir = join3(ruleFixturesDir, "vulnerable");
761
- const fixedDir = join3(ruleFixturesDir, "fixed");
762
- if (!existsSync3(vulnerableDir) || !existsSync3(fixedDir)) {
373
+ const ruleFixturesDir = join(fixturesRoot, rule.id);
374
+ const vulnerableDir = join(ruleFixturesDir, "vulnerable");
375
+ const fixedDir = join(ruleFixturesDir, "fixed");
376
+ if (!existsSync(vulnerableDir) || !existsSync(fixedDir)) {
763
377
  return {
764
378
  ruleId: rule.id,
765
379
  status: "missing-fixtures",
@@ -792,10 +406,10 @@ function validatePack(dir) {
792
406
 
793
407
  // src/telemetry.ts
794
408
  import { createHash, randomUUID } from "crypto";
795
- import { appendFileSync, existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
409
+ import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
796
410
  import { execFileSync } from "child_process";
797
- import { homedir as homedir2 } from "os";
798
- import { dirname as dirname2, join as join4, resolve } from "path";
411
+ import { homedir } from "os";
412
+ import { dirname, join as join2, resolve } from "path";
799
413
  function sha256Hex(s) {
800
414
  return createHash("sha256").update(s).digest("hex");
801
415
  }
@@ -803,24 +417,24 @@ function isTelemetryEnabled(targetDir) {
803
417
  const env = process.env.BRAINBLAST_TELEMETRY;
804
418
  if (env === "1" || env === "true") return true;
805
419
  if (env === "0" || env === "false") return false;
806
- const configPath = join4(targetDir, ".agent-research", "config.json");
807
- if (!existsSync4(configPath)) return false;
420
+ const configPath = join2(targetDir, ".agent-research", "config.json");
421
+ if (!existsSync2(configPath)) return false;
808
422
  try {
809
- const cfg = JSON.parse(readFileSync4(configPath, "utf8"));
423
+ const cfg = JSON.parse(readFileSync2(configPath, "utf8"));
810
424
  return cfg?.telemetry === true;
811
425
  } catch {
812
426
  return false;
813
427
  }
814
428
  }
815
429
  function getUserHash() {
816
- const idPath = join4(homedir2(), ".brainblast", "telemetry-id");
430
+ const idPath = join2(homedir(), ".brainblast", "telemetry-id");
817
431
  let id;
818
- if (existsSync4(idPath)) {
819
- id = readFileSync4(idPath, "utf8").trim();
432
+ if (existsSync2(idPath)) {
433
+ id = readFileSync2(idPath, "utf8").trim();
820
434
  } else {
821
435
  id = randomUUID();
822
- mkdirSync3(dirname2(idPath), { recursive: true });
823
- writeFileSync4(idPath, id, "utf8");
436
+ mkdirSync2(dirname(idPath), { recursive: true });
437
+ writeFileSync3(idPath, id, "utf8");
824
438
  }
825
439
  return sha256Hex(id).slice(0, 16);
826
440
  }
@@ -838,15 +452,15 @@ function getRepoHash(targetDir) {
838
452
  return sha256Hex(key).slice(0, 16);
839
453
  }
840
454
  function telemetryFilePath(targetDir) {
841
- return join4(targetDir, ".agent-research", "telemetry.ndjson");
455
+ return join2(targetDir, ".agent-research", "telemetry.ndjson");
842
456
  }
843
457
  var DEFAULT_REGISTRY_URL = "https://registry.brainblast.tech";
844
458
  async function submitTelemetry(targetDir, registryUrl = process.env.BRAINBLAST_REGISTRY_URL || DEFAULT_REGISTRY_URL) {
845
459
  const file = telemetryFilePath(targetDir);
846
- if (!existsSync4(file)) {
460
+ if (!existsSync2(file)) {
847
461
  return { submitted: 0, accepted: 0, rejected: 0, graduations: [] };
848
462
  }
849
- const events = readFileSync4(file, "utf8").trim().split("\n").filter(Boolean).map((line) => JSON.parse(line));
463
+ const events = readFileSync2(file, "utf8").trim().split("\n").filter(Boolean).map((line) => JSON.parse(line));
850
464
  if (events.length === 0) {
851
465
  return { submitted: 0, accepted: 0, rejected: 0, graduations: [] };
852
466
  }
@@ -865,7 +479,7 @@ async function submitTelemetry(targetDir, registryUrl = process.env.BRAINBLAST_R
865
479
  function recordGraduationEvents(targetDir, events) {
866
480
  if (events.length === 0) return;
867
481
  const file = telemetryFilePath(targetDir);
868
- mkdirSync3(dirname2(file), { recursive: true });
482
+ mkdirSync2(dirname(file), { recursive: true });
869
483
  const repo_hash = getRepoHash(targetDir);
870
484
  const user_hash = getUserHash();
871
485
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -874,21 +488,6 @@ function recordGraduationEvents(targetDir, events) {
874
488
  }
875
489
 
876
490
  export {
877
- loadDirectory,
878
- base58Encode,
879
- base58Decode,
880
- isValidSolanaAddress,
881
- DEFAULT_TTL_HOURS,
882
- defaultCachePath,
883
- loadProgramCache,
884
- saveProgramCache,
885
- getCacheEntry,
886
- putCacheEntry,
887
- getCacheEntryMeta,
888
- isEntryExpired,
889
- cacheSize,
890
- buildTrustGraph,
891
- renderTrustGraphMd,
892
491
  rentExemptMinimum,
893
492
  lamportsToSol,
894
493
  analyzeCosts,