@codacy/verity-cli 0.27.1 → 0.27.2
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/bin/verity.js +334 -221
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -10483,91 +10483,6 @@ function githubAppInstallUrl(accountId) {
|
|
|
10483
10483
|
return accountId != null ? `https://github.com/apps/${GITHUB_APP_SLUG}/installations/new/permissions?target_id=${accountId}` : GITHUB_APP_INSTALL_URL;
|
|
10484
10484
|
}
|
|
10485
10485
|
|
|
10486
|
-
// src/lib/auth.ts
|
|
10487
|
-
async function resolveToken(flagToken) {
|
|
10488
|
-
if (flagToken) {
|
|
10489
|
-
return { ok: true, data: { token: flagToken, source: "flag" } };
|
|
10490
|
-
}
|
|
10491
|
-
const envToken = process.env.VERITY_TOKEN;
|
|
10492
|
-
if (envToken) {
|
|
10493
|
-
return { ok: true, data: { token: envToken, source: "env" } };
|
|
10494
|
-
}
|
|
10495
|
-
try {
|
|
10496
|
-
const content = await (0, import_promises.readFile)(projectPath(CREDENTIALS_FILE), "utf-8");
|
|
10497
|
-
const match = content.match(/token:\s*((?:gate_|verity_)[a-f0-9]+)/);
|
|
10498
|
-
if (match) {
|
|
10499
|
-
return { ok: true, data: { token: match[1], source: "local" } };
|
|
10500
|
-
}
|
|
10501
|
-
} catch {
|
|
10502
|
-
}
|
|
10503
|
-
const globalCredentials = `${process.env.HOME}/.verity/credentials`;
|
|
10504
|
-
try {
|
|
10505
|
-
const content = await (0, import_promises.readFile)(globalCredentials, "utf-8");
|
|
10506
|
-
let remote = "";
|
|
10507
|
-
try {
|
|
10508
|
-
remote = (0, import_node_child_process2.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
|
|
10509
|
-
} catch {
|
|
10510
|
-
}
|
|
10511
|
-
if (remote) {
|
|
10512
|
-
const remoteLine = content.split("\n").find((l) => l.includes(remote));
|
|
10513
|
-
if (remoteLine) {
|
|
10514
|
-
const match = remoteLine.match(/token:\s*((?:gate_|verity_)[a-f0-9]+)/);
|
|
10515
|
-
if (match) {
|
|
10516
|
-
return { ok: true, data: { token: match[1], source: "global" } };
|
|
10517
|
-
}
|
|
10518
|
-
}
|
|
10519
|
-
}
|
|
10520
|
-
const plainMatch = content.match(/^token:\s*((?:gate_|verity_)[a-f0-9]+)/m);
|
|
10521
|
-
if (plainMatch) {
|
|
10522
|
-
return { ok: true, data: { token: plainMatch[1], source: "global" } };
|
|
10523
|
-
}
|
|
10524
|
-
} catch {
|
|
10525
|
-
}
|
|
10526
|
-
return { ok: false, error: "No Verity token found. Run /verity-setup to configure." };
|
|
10527
|
-
}
|
|
10528
|
-
|
|
10529
|
-
// src/lib/service-url.ts
|
|
10530
|
-
var import_promises2 = require("node:fs/promises");
|
|
10531
|
-
async function resolveServiceUrl(flagUrl) {
|
|
10532
|
-
if (flagUrl) {
|
|
10533
|
-
return { ok: true, data: flagUrl };
|
|
10534
|
-
}
|
|
10535
|
-
const envUrl = process.env.VERITY_SERVICE_URL;
|
|
10536
|
-
if (envUrl) {
|
|
10537
|
-
return { ok: true, data: envUrl };
|
|
10538
|
-
}
|
|
10539
|
-
try {
|
|
10540
|
-
const creds = await (0, import_promises2.readFile)(projectPath(CREDENTIALS_FILE), "utf-8");
|
|
10541
|
-
const match = creds.match(/service_url:\s*(https?:\/\/[^\s]+)/);
|
|
10542
|
-
if (match) {
|
|
10543
|
-
return { ok: true, data: match[1] };
|
|
10544
|
-
}
|
|
10545
|
-
} catch {
|
|
10546
|
-
}
|
|
10547
|
-
try {
|
|
10548
|
-
const content = await (0, import_promises2.readFile)(projectPath(VERITY_MD_FILE), "utf-8");
|
|
10549
|
-
const boldMatch = content.match(/\*\*url\*\*/i);
|
|
10550
|
-
if (boldMatch) {
|
|
10551
|
-
const lineMatch = content.split("\n").find((l) => /\*\*url\*\*/i.test(l));
|
|
10552
|
-
if (lineMatch) {
|
|
10553
|
-
const urlMatch = lineMatch.match(/https:\/\/[^\s]+/);
|
|
10554
|
-
if (urlMatch) {
|
|
10555
|
-
return { ok: true, data: urlMatch[0] };
|
|
10556
|
-
}
|
|
10557
|
-
}
|
|
10558
|
-
}
|
|
10559
|
-
const plainLine = content.split("\n").find((l) => /(?:url|service)\s*:/i.test(l));
|
|
10560
|
-
if (plainLine) {
|
|
10561
|
-
const urlMatch = plainLine.match(/https:\/\/[^\s]+/);
|
|
10562
|
-
if (urlMatch) {
|
|
10563
|
-
return { ok: true, data: urlMatch[0] };
|
|
10564
|
-
}
|
|
10565
|
-
}
|
|
10566
|
-
} catch {
|
|
10567
|
-
}
|
|
10568
|
-
return { ok: false, error: "No Verity service URL found. Run /verity-setup to configure." };
|
|
10569
|
-
}
|
|
10570
|
-
|
|
10571
10486
|
// src/lib/output.ts
|
|
10572
10487
|
var RED = "\x1B[0;31m";
|
|
10573
10488
|
var YELLOW = "\x1B[1;33m";
|
|
@@ -10750,6 +10665,108 @@ function analyzeRequest(options) {
|
|
|
10750
10665
|
});
|
|
10751
10666
|
}
|
|
10752
10667
|
|
|
10668
|
+
// src/lib/auth.ts
|
|
10669
|
+
function parseIdentity(content) {
|
|
10670
|
+
const idMatch = content.match(/^user_id:\s*(\d+)/m);
|
|
10671
|
+
const emailMatch = content.match(/^email:\s*(\S+)/m);
|
|
10672
|
+
return {
|
|
10673
|
+
userId: idMatch ? Number(idMatch[1]) : void 0,
|
|
10674
|
+
email: emailMatch ? emailMatch[1] : void 0
|
|
10675
|
+
};
|
|
10676
|
+
}
|
|
10677
|
+
async function resolveToken(flagToken) {
|
|
10678
|
+
if (flagToken) {
|
|
10679
|
+
return { ok: true, data: { token: flagToken, source: "flag" } };
|
|
10680
|
+
}
|
|
10681
|
+
const envToken = process.env.VERITY_TOKEN;
|
|
10682
|
+
if (envToken) {
|
|
10683
|
+
return { ok: true, data: { token: envToken, source: "env" } };
|
|
10684
|
+
}
|
|
10685
|
+
try {
|
|
10686
|
+
const content = await (0, import_promises.readFile)(projectPath(CREDENTIALS_FILE), "utf-8");
|
|
10687
|
+
const match = content.match(/token:\s*((?:gate_|verity_)[a-f0-9]+)/);
|
|
10688
|
+
if (match) {
|
|
10689
|
+
return { ok: true, data: { token: match[1], source: "local", ...parseIdentity(content) } };
|
|
10690
|
+
}
|
|
10691
|
+
} catch {
|
|
10692
|
+
}
|
|
10693
|
+
const globalCredentials = `${process.env.HOME}/.verity/credentials`;
|
|
10694
|
+
try {
|
|
10695
|
+
const content = await (0, import_promises.readFile)(globalCredentials, "utf-8");
|
|
10696
|
+
let remote = "";
|
|
10697
|
+
try {
|
|
10698
|
+
remote = (0, import_node_child_process2.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
|
|
10699
|
+
} catch {
|
|
10700
|
+
}
|
|
10701
|
+
if (remote) {
|
|
10702
|
+
const remoteLine = content.split("\n").find((l) => l.includes(remote));
|
|
10703
|
+
if (remoteLine) {
|
|
10704
|
+
const match = remoteLine.match(/token:\s*((?:gate_|verity_)[a-f0-9]+)/);
|
|
10705
|
+
if (match) {
|
|
10706
|
+
return { ok: true, data: { token: match[1], source: "global" } };
|
|
10707
|
+
}
|
|
10708
|
+
}
|
|
10709
|
+
}
|
|
10710
|
+
const plainMatch = content.match(/^token:\s*((?:gate_|verity_)[a-f0-9]+)/m);
|
|
10711
|
+
if (plainMatch) {
|
|
10712
|
+
return { ok: true, data: { token: plainMatch[1], source: "global" } };
|
|
10713
|
+
}
|
|
10714
|
+
} catch {
|
|
10715
|
+
}
|
|
10716
|
+
return { ok: false, error: "No Verity token found. Run /verity-setup to configure." };
|
|
10717
|
+
}
|
|
10718
|
+
async function whoami(token, serviceUrl, verbose) {
|
|
10719
|
+
return apiRequest({
|
|
10720
|
+
method: "GET",
|
|
10721
|
+
path: "/auth/whoami",
|
|
10722
|
+
serviceUrl,
|
|
10723
|
+
token,
|
|
10724
|
+
verbose
|
|
10725
|
+
});
|
|
10726
|
+
}
|
|
10727
|
+
|
|
10728
|
+
// src/lib/service-url.ts
|
|
10729
|
+
var import_promises2 = require("node:fs/promises");
|
|
10730
|
+
async function resolveServiceUrl(flagUrl) {
|
|
10731
|
+
if (flagUrl) {
|
|
10732
|
+
return { ok: true, data: flagUrl };
|
|
10733
|
+
}
|
|
10734
|
+
const envUrl = process.env.VERITY_SERVICE_URL;
|
|
10735
|
+
if (envUrl) {
|
|
10736
|
+
return { ok: true, data: envUrl };
|
|
10737
|
+
}
|
|
10738
|
+
try {
|
|
10739
|
+
const creds = await (0, import_promises2.readFile)(projectPath(CREDENTIALS_FILE), "utf-8");
|
|
10740
|
+
const match = creds.match(/service_url:\s*(https?:\/\/[^\s]+)/);
|
|
10741
|
+
if (match) {
|
|
10742
|
+
return { ok: true, data: match[1] };
|
|
10743
|
+
}
|
|
10744
|
+
} catch {
|
|
10745
|
+
}
|
|
10746
|
+
try {
|
|
10747
|
+
const content = await (0, import_promises2.readFile)(projectPath(VERITY_MD_FILE), "utf-8");
|
|
10748
|
+
const boldMatch = content.match(/\*\*url\*\*/i);
|
|
10749
|
+
if (boldMatch) {
|
|
10750
|
+
const lineMatch = content.split("\n").find((l) => /\*\*url\*\*/i.test(l));
|
|
10751
|
+
if (lineMatch) {
|
|
10752
|
+
const urlMatch = lineMatch.match(/https:\/\/[^\s]+/);
|
|
10753
|
+
if (urlMatch) {
|
|
10754
|
+
return { ok: true, data: urlMatch[0] };
|
|
10755
|
+
}
|
|
10756
|
+
}
|
|
10757
|
+
}
|
|
10758
|
+
const plainLine = content.split("\n").find((l) => /(?:url|service)\s*:/i.test(l));
|
|
10759
|
+
if (plainLine) {
|
|
10760
|
+
const urlMatch = plainLine.match(/https:\/\/[^\s]+/);
|
|
10761
|
+
if (urlMatch) {
|
|
10762
|
+
return { ok: true, data: urlMatch[0] };
|
|
10763
|
+
}
|
|
10764
|
+
}
|
|
10765
|
+
} catch {
|
|
10766
|
+
}
|
|
10767
|
+
return { ok: false, error: "No Verity service URL found. Run /verity-setup to configure." };
|
|
10768
|
+
}
|
|
10769
|
+
|
|
10753
10770
|
// src/lib/register.ts
|
|
10754
10771
|
var import_promises3 = require("node:fs/promises");
|
|
10755
10772
|
var import_node_path3 = require("node:path");
|
|
@@ -11047,8 +11064,8 @@ function filterReviewable(files) {
|
|
|
11047
11064
|
const ext = (0, import_node_path2.extname)(f).slice(1);
|
|
11048
11065
|
if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
|
|
11049
11066
|
if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
|
|
11050
|
-
const
|
|
11051
|
-
if (REVIEWABLE_FILENAMES.has(
|
|
11067
|
+
const basename4 = f.split("/").pop() ?? "";
|
|
11068
|
+
if (REVIEWABLE_FILENAMES.has(basename4)) return true;
|
|
11052
11069
|
if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
|
|
11053
11070
|
return false;
|
|
11054
11071
|
});
|
|
@@ -11174,13 +11191,18 @@ async function registerProject(opts) {
|
|
|
11174
11191
|
return { ok: false, error: result.error };
|
|
11175
11192
|
}
|
|
11176
11193
|
const { project_id, token, service_url, user } = result.data;
|
|
11194
|
+
const userId = result.data.user_id ?? user?.id;
|
|
11195
|
+
const email = user?.email;
|
|
11196
|
+
const identityLines = (userId != null ? `user_id: ${userId}
|
|
11197
|
+
` : "") + (email ? `email: ${email}
|
|
11198
|
+
` : "");
|
|
11177
11199
|
try {
|
|
11178
11200
|
await (0, import_promises3.mkdir)(VERITY_DIR, { recursive: true });
|
|
11179
11201
|
await (0, import_promises3.writeFile)(
|
|
11180
11202
|
CREDENTIALS_FILE,
|
|
11181
11203
|
`token: ${token}
|
|
11182
11204
|
service_url: ${service_url}
|
|
11183
|
-
`,
|
|
11205
|
+
${identityLines}`,
|
|
11184
11206
|
{ mode: 384 }
|
|
11185
11207
|
);
|
|
11186
11208
|
await (0, import_promises3.chmod)(CREDENTIALS_FILE, 384).catch(() => {
|
|
@@ -11203,7 +11225,7 @@ service_url: ${service_url}
|
|
|
11203
11225
|
});
|
|
11204
11226
|
} catch {
|
|
11205
11227
|
}
|
|
11206
|
-
return { ok: true, data: { projectId: project_id, serviceUrl: service_url, email
|
|
11228
|
+
return { ok: true, data: { projectId: project_id, serviceUrl: service_url, email, userId } };
|
|
11207
11229
|
}
|
|
11208
11230
|
|
|
11209
11231
|
// src/commands/auth.ts
|
|
@@ -11293,13 +11315,70 @@ function registerAuthCommands(program2) {
|
|
|
11293
11315
|
});
|
|
11294
11316
|
}
|
|
11295
11317
|
|
|
11318
|
+
// src/commands/login.ts
|
|
11319
|
+
var import_node_child_process5 = require("node:child_process");
|
|
11320
|
+
var import_node_path4 = require("node:path");
|
|
11321
|
+
function registerLoginCommand(program2) {
|
|
11322
|
+
program2.command("login").description("Log in to Verity (link your GitHub identity so runs and memory are saved)").option("--force", "Re-authenticate even if already logged in").action(async (opts) => {
|
|
11323
|
+
const globals = program2.opts();
|
|
11324
|
+
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
11325
|
+
if (!urlResult.ok) {
|
|
11326
|
+
printError(urlResult.error);
|
|
11327
|
+
process.exit(1);
|
|
11328
|
+
}
|
|
11329
|
+
const serviceUrl = urlResult.data;
|
|
11330
|
+
const existing = await resolveToken(globals.token);
|
|
11331
|
+
if (existing.ok && !opts.force) {
|
|
11332
|
+
if (existing.data.userId != null) {
|
|
11333
|
+
printInfo(`Already logged in as ${existing.data.email ?? `user #${existing.data.userId}`}. \u2713`);
|
|
11334
|
+
printInfo(" Re-authenticate with: verity login --force");
|
|
11335
|
+
return;
|
|
11336
|
+
}
|
|
11337
|
+
const who2 = await whoami(existing.data.token, serviceUrl, globals.verbose);
|
|
11338
|
+
if (who2.ok && who2.data.logged_in) {
|
|
11339
|
+
printInfo(`Already logged in as ${who2.data.email ?? `user #${who2.data.user_id}`}. \u2713`);
|
|
11340
|
+
printInfo(" Re-authenticate with: verity login --force");
|
|
11341
|
+
return;
|
|
11342
|
+
}
|
|
11343
|
+
if (who2.ok && who2.data.anonymous) {
|
|
11344
|
+
printInfo("You have an anonymous token (the gate runs, but nothing is saved). Logging you in\u2026");
|
|
11345
|
+
} else if (!who2.ok) {
|
|
11346
|
+
printWarn("Could not confirm your current login state with the service \u2014 proceeding to log in.");
|
|
11347
|
+
}
|
|
11348
|
+
}
|
|
11349
|
+
let remote = "";
|
|
11350
|
+
try {
|
|
11351
|
+
remote = (0, import_node_child_process5.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
11352
|
+
} catch {
|
|
11353
|
+
}
|
|
11354
|
+
if (!remote) {
|
|
11355
|
+
printError("verity login needs a git remote (origin) to link this repository.");
|
|
11356
|
+
printInfo(" Add one with: git remote add origin <url>, then re-run verity login.");
|
|
11357
|
+
process.exit(1);
|
|
11358
|
+
}
|
|
11359
|
+
const projectName = parseRemote(remote)?.repo ?? (0, import_node_path4.basename)(process.cwd());
|
|
11360
|
+
printInfo("Authenticating with GitHub\u2026");
|
|
11361
|
+
const result = await registerProject({ projectName, remote, serviceUrl, verbose: globals.verbose });
|
|
11362
|
+
if (!result.ok) {
|
|
11363
|
+
printError(`Login failed: ${result.error}`);
|
|
11364
|
+
process.exit(1);
|
|
11365
|
+
}
|
|
11366
|
+
const who = result.data.email ?? (result.data.userId != null ? `user #${result.data.userId}` : "your account");
|
|
11367
|
+
printInfo(`Logged in as ${who}. \u2713`);
|
|
11368
|
+
printInfo(" Runs, history, and cloud memory now sync to Verity for this project.");
|
|
11369
|
+
if (result.data.userId == null) {
|
|
11370
|
+
printWarn(" (Server did not return a user id \u2014 update the CLI if this persists.)");
|
|
11371
|
+
}
|
|
11372
|
+
});
|
|
11373
|
+
}
|
|
11374
|
+
|
|
11296
11375
|
// src/lib/hooks.ts
|
|
11297
11376
|
var import_promises5 = require("node:fs/promises");
|
|
11298
|
-
var
|
|
11377
|
+
var import_node_path6 = require("node:path");
|
|
11299
11378
|
|
|
11300
11379
|
// src/lib/json-file.ts
|
|
11301
11380
|
var import_promises4 = require("node:fs/promises");
|
|
11302
|
-
var
|
|
11381
|
+
var import_node_path5 = require("node:path");
|
|
11303
11382
|
function jsonSemanticEqual(a, b) {
|
|
11304
11383
|
if (a === b) return true;
|
|
11305
11384
|
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) {
|
|
@@ -11345,7 +11424,7 @@ async function writeJsonFilePreservingStyle(file, value) {
|
|
|
11345
11424
|
const indent = currentRaw !== null ? detectJsonIndent(currentRaw) : 2;
|
|
11346
11425
|
const next = JSON.stringify(value, null, indent) + "\n";
|
|
11347
11426
|
if (next === currentRaw) return false;
|
|
11348
|
-
await (0, import_promises4.mkdir)((0,
|
|
11427
|
+
await (0, import_promises4.mkdir)((0, import_node_path5.dirname)(file), { recursive: true });
|
|
11349
11428
|
await (0, import_promises4.writeFile)(file, next);
|
|
11350
11429
|
return true;
|
|
11351
11430
|
}
|
|
@@ -11506,13 +11585,13 @@ async function writeSettings(settings) {
|
|
|
11506
11585
|
}
|
|
11507
11586
|
async function readSettingsAt(root) {
|
|
11508
11587
|
try {
|
|
11509
|
-
return JSON.parse(await (0, import_promises5.readFile)((0,
|
|
11588
|
+
return JSON.parse(await (0, import_promises5.readFile)((0, import_node_path6.join)(root, CLAUDE_SETTINGS_FILE), "utf-8"));
|
|
11510
11589
|
} catch {
|
|
11511
11590
|
return {};
|
|
11512
11591
|
}
|
|
11513
11592
|
}
|
|
11514
11593
|
async function writeSettingsAt(root, settings) {
|
|
11515
|
-
await writeJsonFilePreservingStyle((0,
|
|
11594
|
+
await writeJsonFilePreservingStyle((0, import_node_path6.join)(root, CLAUDE_SETTINGS_FILE), settings);
|
|
11516
11595
|
}
|
|
11517
11596
|
async function hasLegacyHooksAt(root) {
|
|
11518
11597
|
const settings = await readSettingsAt(root);
|
|
@@ -11753,7 +11832,7 @@ var import_node_crypto3 = require("node:crypto");
|
|
|
11753
11832
|
// src/lib/conversation-buffer.ts
|
|
11754
11833
|
var import_promises6 = require("node:fs/promises");
|
|
11755
11834
|
var import_node_fs3 = require("node:fs");
|
|
11756
|
-
var
|
|
11835
|
+
var import_node_child_process6 = require("node:child_process");
|
|
11757
11836
|
var import_node_crypto = require("node:crypto");
|
|
11758
11837
|
function stripImageReferences(text) {
|
|
11759
11838
|
return text.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
|
|
@@ -11856,7 +11935,7 @@ async function readBufferEntries() {
|
|
|
11856
11935
|
}
|
|
11857
11936
|
function getRecentCommitMessages() {
|
|
11858
11937
|
try {
|
|
11859
|
-
const output = (0,
|
|
11938
|
+
const output = (0, import_node_child_process6.execSync)(
|
|
11860
11939
|
'git log --since="30 minutes ago" --format="%s" -5',
|
|
11861
11940
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
11862
11941
|
).trim();
|
|
@@ -11870,7 +11949,7 @@ function getRecentCommitMessages() {
|
|
|
11870
11949
|
// src/lib/task-context-buffer.ts
|
|
11871
11950
|
var import_promises7 = require("node:fs/promises");
|
|
11872
11951
|
var import_node_fs4 = require("node:fs");
|
|
11873
|
-
var
|
|
11952
|
+
var import_node_path7 = require("node:path");
|
|
11874
11953
|
var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
|
|
11875
11954
|
var MAX_BUFFER_BYTES = 500 * 1024;
|
|
11876
11955
|
var MAX_PROMPT_CHARS = 2e3;
|
|
@@ -11948,7 +12027,7 @@ async function cleanupTaskContextBuffers() {
|
|
|
11948
12027
|
const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
11949
12028
|
for (const file of files) {
|
|
11950
12029
|
if (!file.endsWith(".jsonl")) continue;
|
|
11951
|
-
const filePath = (0,
|
|
12030
|
+
const filePath = (0, import_node_path7.join)(TASK_CONTEXT_DIR, file);
|
|
11952
12031
|
try {
|
|
11953
12032
|
const stats = await (0, import_promises7.stat)(filePath);
|
|
11954
12033
|
if (stats.mtimeMs < cutoffMs) {
|
|
@@ -11962,7 +12041,7 @@ async function cleanupTaskContextBuffers() {
|
|
|
11962
12041
|
}
|
|
11963
12042
|
function bufferPath(taskId) {
|
|
11964
12043
|
const safe = taskId.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
11965
|
-
return (0,
|
|
12044
|
+
return (0, import_node_path7.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
|
|
11966
12045
|
}
|
|
11967
12046
|
async function appendEntry(taskId, entry) {
|
|
11968
12047
|
try {
|
|
@@ -11988,7 +12067,7 @@ async function appendEntry(taskId, entry) {
|
|
|
11988
12067
|
// src/lib/memory-retrieval.ts
|
|
11989
12068
|
var import_promises8 = require("node:fs/promises");
|
|
11990
12069
|
var import_node_fs5 = require("node:fs");
|
|
11991
|
-
var
|
|
12070
|
+
var import_node_path8 = require("node:path");
|
|
11992
12071
|
var memoryDir = () => projectPath(`${VERITY_DIR}/memory`);
|
|
11993
12072
|
var DOMAINS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
|
|
11994
12073
|
var DEFAULT_BUDGET_TOKENS = 2e3;
|
|
@@ -12086,14 +12165,14 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
12086
12165
|
const promptTokens = tokenize(promptText);
|
|
12087
12166
|
const nodes = [];
|
|
12088
12167
|
for (const domain of DOMAINS) {
|
|
12089
|
-
const domainDir = (0,
|
|
12168
|
+
const domainDir = (0, import_node_path8.join)(memoryDir(), domain);
|
|
12090
12169
|
if (!(0, import_node_fs5.existsSync)(domainDir)) continue;
|
|
12091
12170
|
try {
|
|
12092
12171
|
const files = await (0, import_promises8.readdir)(domainDir);
|
|
12093
12172
|
for (const file of files) {
|
|
12094
12173
|
if (!file.endsWith(".md")) continue;
|
|
12095
12174
|
try {
|
|
12096
|
-
const content = await (0, import_promises8.readFile)((0,
|
|
12175
|
+
const content = await (0, import_promises8.readFile)((0, import_node_path8.join)(domainDir, file), "utf-8");
|
|
12097
12176
|
const { fm, body } = parseFrontmatter(content);
|
|
12098
12177
|
if (fm.status && fm.status !== "active") continue;
|
|
12099
12178
|
nodes.push({
|
|
@@ -12153,7 +12232,7 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
12153
12232
|
// src/lib/memory-sync.ts
|
|
12154
12233
|
var import_promises9 = require("node:fs/promises");
|
|
12155
12234
|
var import_node_fs6 = require("node:fs");
|
|
12156
|
-
var
|
|
12235
|
+
var import_node_path9 = require("node:path");
|
|
12157
12236
|
var import_node_crypto2 = require("node:crypto");
|
|
12158
12237
|
|
|
12159
12238
|
// src/lib/glob-match.ts
|
|
@@ -12224,16 +12303,16 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
|
|
|
12224
12303
|
async function ensureMemoryDir() {
|
|
12225
12304
|
await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
|
|
12226
12305
|
for (const domain of DOMAINS2) {
|
|
12227
|
-
await (0, import_promises9.mkdir)((0,
|
|
12306
|
+
await (0, import_promises9.mkdir)((0, import_node_path9.join)(memoryDir2(), domain), { recursive: true });
|
|
12228
12307
|
}
|
|
12229
|
-
if (!(0, import_node_fs6.existsSync)((0,
|
|
12230
|
-
await (0, import_promises9.writeFile)((0,
|
|
12308
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path9.join)(memoryDir2(), "SCHEMA.md"))) {
|
|
12309
|
+
await (0, import_promises9.writeFile)((0, import_node_path9.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
|
|
12231
12310
|
}
|
|
12232
|
-
if (!(0, import_node_fs6.existsSync)((0,
|
|
12233
|
-
await (0, import_promises9.writeFile)((0,
|
|
12311
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path9.join)(memoryDir2(), "index.md"))) {
|
|
12312
|
+
await (0, import_promises9.writeFile)((0, import_node_path9.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
|
|
12234
12313
|
}
|
|
12235
|
-
if (!(0, import_node_fs6.existsSync)((0,
|
|
12236
|
-
await (0, import_promises9.writeFile)((0,
|
|
12314
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path9.join)(memoryDir2(), "log.md"))) {
|
|
12315
|
+
await (0, import_promises9.writeFile)((0, import_node_path9.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
|
|
12237
12316
|
}
|
|
12238
12317
|
}
|
|
12239
12318
|
async function buildManifest() {
|
|
@@ -12242,14 +12321,14 @@ async function buildManifest() {
|
|
|
12242
12321
|
}
|
|
12243
12322
|
const nodes = [];
|
|
12244
12323
|
for (const domain of DOMAINS2) {
|
|
12245
|
-
const domainDir = (0,
|
|
12324
|
+
const domainDir = (0, import_node_path9.join)(memoryDir2(), domain);
|
|
12246
12325
|
if (!(0, import_node_fs6.existsSync)(domainDir)) continue;
|
|
12247
12326
|
try {
|
|
12248
12327
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
12249
12328
|
for (const file of files) {
|
|
12250
12329
|
if (!file.endsWith(".md")) continue;
|
|
12251
12330
|
const filePath = `${domain}/${file}`;
|
|
12252
|
-
const fullPath = (0,
|
|
12331
|
+
const fullPath = (0, import_node_path9.join)(memoryDir2(), filePath);
|
|
12253
12332
|
try {
|
|
12254
12333
|
const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
12255
12334
|
const hash = (0, import_node_crypto2.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
@@ -12262,13 +12341,13 @@ async function buildManifest() {
|
|
|
12262
12341
|
}
|
|
12263
12342
|
let indexHash = null;
|
|
12264
12343
|
try {
|
|
12265
|
-
const indexContent = await (0, import_promises9.readFile)((0,
|
|
12344
|
+
const indexContent = await (0, import_promises9.readFile)((0, import_node_path9.join)(memoryDir2(), "index.md"), "utf-8");
|
|
12266
12345
|
indexHash = `sha256:${(0, import_node_crypto2.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
|
|
12267
12346
|
} catch {
|
|
12268
12347
|
}
|
|
12269
12348
|
let logLength = 0;
|
|
12270
12349
|
try {
|
|
12271
|
-
const logContent = await (0, import_promises9.readFile)((0,
|
|
12350
|
+
const logContent = await (0, import_promises9.readFile)((0, import_node_path9.join)(memoryDir2(), "log.md"), "utf-8");
|
|
12272
12351
|
logLength = logContent.split("\n").length;
|
|
12273
12352
|
} catch {
|
|
12274
12353
|
}
|
|
@@ -12281,13 +12360,13 @@ async function readOnDiskNodes() {
|
|
|
12281
12360
|
const out = /* @__PURE__ */ new Map();
|
|
12282
12361
|
if (!(0, import_node_fs6.existsSync)(memoryDir2())) return out;
|
|
12283
12362
|
for (const domain of DOMAINS2) {
|
|
12284
|
-
const domainDir = (0,
|
|
12363
|
+
const domainDir = (0, import_node_path9.join)(memoryDir2(), domain);
|
|
12285
12364
|
if (!(0, import_node_fs6.existsSync)(domainDir)) continue;
|
|
12286
12365
|
try {
|
|
12287
12366
|
for (const file of await (0, import_promises9.readdir)(domainDir)) {
|
|
12288
12367
|
if (!file.endsWith(".md")) continue;
|
|
12289
12368
|
try {
|
|
12290
|
-
out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0,
|
|
12369
|
+
out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path9.join)(domainDir, file), "utf-8")));
|
|
12291
12370
|
} catch {
|
|
12292
12371
|
}
|
|
12293
12372
|
}
|
|
@@ -12333,7 +12412,7 @@ async function computeEditedNodeUploads() {
|
|
|
12333
12412
|
const uploads = [];
|
|
12334
12413
|
for (const [path, prevHash] of prev) {
|
|
12335
12414
|
if (prevHash == null) continue;
|
|
12336
|
-
const full = (0,
|
|
12415
|
+
const full = (0, import_node_path9.join)(memoryDir2(), path);
|
|
12337
12416
|
if (!(0, import_node_fs6.existsSync)(full)) continue;
|
|
12338
12417
|
let content;
|
|
12339
12418
|
try {
|
|
@@ -12370,15 +12449,15 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
12370
12449
|
const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
|
|
12371
12450
|
for (const n of notes) logLines.push(` - ${n}`);
|
|
12372
12451
|
try {
|
|
12373
|
-
const existing = (0, import_node_fs6.existsSync)((0,
|
|
12374
|
-
await (0, import_promises9.writeFile)((0,
|
|
12452
|
+
const existing = (0, import_node_fs6.existsSync)((0, import_node_path9.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path9.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
|
|
12453
|
+
await (0, import_promises9.writeFile)((0, import_node_path9.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
|
|
12375
12454
|
} catch {
|
|
12376
12455
|
}
|
|
12377
12456
|
await recordSyncedNodePaths();
|
|
12378
12457
|
return count;
|
|
12379
12458
|
}
|
|
12380
12459
|
async function applyOneWrite(write, treePaths) {
|
|
12381
|
-
const fullPath = (0,
|
|
12460
|
+
const fullPath = (0, import_node_path9.join)(memoryDir2(), write.path);
|
|
12382
12461
|
const notes = [];
|
|
12383
12462
|
let content = write.content;
|
|
12384
12463
|
if (treePaths && treePaths.length > 0) {
|
|
@@ -12400,7 +12479,7 @@ async function applyOneWrite(write, treePaths) {
|
|
|
12400
12479
|
return { written: false, notes };
|
|
12401
12480
|
}
|
|
12402
12481
|
}
|
|
12403
|
-
await (0, import_promises9.mkdir)((0,
|
|
12482
|
+
await (0, import_promises9.mkdir)((0, import_node_path9.dirname)(fullPath), { recursive: true });
|
|
12404
12483
|
await (0, import_promises9.writeFile)(fullPath, content);
|
|
12405
12484
|
return { written: true, notes };
|
|
12406
12485
|
}
|
|
@@ -12441,7 +12520,7 @@ async function regenerateIndex() {
|
|
|
12441
12520
|
];
|
|
12442
12521
|
let totalNodes = 0;
|
|
12443
12522
|
for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
|
|
12444
|
-
const domainDir = (0,
|
|
12523
|
+
const domainDir = (0, import_node_path9.join)(memoryDir2(), domain);
|
|
12445
12524
|
if (!(0, import_node_fs6.existsSync)(domainDir)) continue;
|
|
12446
12525
|
try {
|
|
12447
12526
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
@@ -12452,7 +12531,7 @@ async function regenerateIndex() {
|
|
|
12452
12531
|
for (const file of mdFiles.sort()) {
|
|
12453
12532
|
const slug = file.replace(/\.md$/, "");
|
|
12454
12533
|
try {
|
|
12455
|
-
const content = await (0, import_promises9.readFile)((0,
|
|
12534
|
+
const content = await (0, import_promises9.readFile)((0, import_node_path9.join)(domainDir, file), "utf-8");
|
|
12456
12535
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
12457
12536
|
const kind = pickFrontmatter(content, "kind") ?? "-";
|
|
12458
12537
|
const confidence = pickFrontmatter(content, "confidence");
|
|
@@ -12476,7 +12555,7 @@ async function regenerateIndex() {
|
|
|
12476
12555
|
lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
|
|
12477
12556
|
}
|
|
12478
12557
|
const next = lines.join("\n") + "\n";
|
|
12479
|
-
const indexPath = (0,
|
|
12558
|
+
const indexPath = (0, import_node_path9.join)(memoryDir2(), "index.md");
|
|
12480
12559
|
let existing = null;
|
|
12481
12560
|
try {
|
|
12482
12561
|
existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
|
|
@@ -12558,7 +12637,7 @@ function hasLegacyMemoryBlock(text) {
|
|
|
12558
12637
|
return findMarker(text, LEGACY_MD_START) !== -1;
|
|
12559
12638
|
}
|
|
12560
12639
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
12561
|
-
const claudeMdPath = (0,
|
|
12640
|
+
const claudeMdPath = (0, import_node_path9.join)(cwd, "CLAUDE.md");
|
|
12562
12641
|
let existing = "";
|
|
12563
12642
|
if ((0, import_node_fs6.existsSync)(claudeMdPath)) {
|
|
12564
12643
|
existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
|
|
@@ -13113,6 +13192,16 @@ function registerStatusCommand(program2) {
|
|
|
13113
13192
|
return;
|
|
13114
13193
|
}
|
|
13115
13194
|
printInfo("=== Verity Status ===");
|
|
13195
|
+
if (tokenResult.data.userId != null) {
|
|
13196
|
+
printInfo(`Account: Logged in as ${tokenResult.data.email ?? `user #${tokenResult.data.userId}`} \u2713`);
|
|
13197
|
+
} else {
|
|
13198
|
+
const who = await whoami(token, serviceUrl, globals.verbose);
|
|
13199
|
+
if (who.ok && who.data.logged_in) {
|
|
13200
|
+
printInfo(`Account: Logged in as ${who.data.email ?? `user #${who.data.user_id}`} \u2713`);
|
|
13201
|
+
} else if (who.ok && who.data.anonymous) {
|
|
13202
|
+
printInfo('Account: Anonymous \u2014 runs not saved, no cloud memory. Run "verity login".');
|
|
13203
|
+
}
|
|
13204
|
+
}
|
|
13116
13205
|
if (mem.project_name) printInfo(`Project: ${mem.project_name}`);
|
|
13117
13206
|
if (mem.standard) {
|
|
13118
13207
|
const s = mem.standard;
|
|
@@ -13276,11 +13365,11 @@ async function sendGeneralFeedback(message, opts, globals) {
|
|
|
13276
13365
|
|
|
13277
13366
|
// src/commands/analyze.ts
|
|
13278
13367
|
var import_node_fs19 = require("node:fs");
|
|
13279
|
-
var
|
|
13368
|
+
var import_node_path16 = require("node:path");
|
|
13280
13369
|
|
|
13281
13370
|
// src/lib/files.ts
|
|
13282
13371
|
var import_node_fs8 = require("node:fs");
|
|
13283
|
-
var
|
|
13372
|
+
var import_node_path10 = require("node:path");
|
|
13284
13373
|
var LANG_MAP = {
|
|
13285
13374
|
// Analyzable (static analysis + Gemini)
|
|
13286
13375
|
ts: "typescript",
|
|
@@ -13348,7 +13437,7 @@ var LANG_MAP = {
|
|
|
13348
13437
|
mk: "make"
|
|
13349
13438
|
};
|
|
13350
13439
|
function detectLanguage(filepath) {
|
|
13351
|
-
const ext = (0,
|
|
13440
|
+
const ext = (0, import_node_path10.extname)(filepath).slice(1);
|
|
13352
13441
|
return LANG_MAP[ext] ?? ext;
|
|
13353
13442
|
}
|
|
13354
13443
|
function sortByMtime(files) {
|
|
@@ -13543,7 +13632,7 @@ function writeIteration(iteration, commit, _contentHash) {
|
|
|
13543
13632
|
}
|
|
13544
13633
|
|
|
13545
13634
|
// src/lib/static-analysis.ts
|
|
13546
|
-
var
|
|
13635
|
+
var import_node_child_process7 = require("node:child_process");
|
|
13547
13636
|
var import_node_fs10 = require("node:fs");
|
|
13548
13637
|
var SEVERITY_ORDER = {
|
|
13549
13638
|
Error: 0,
|
|
@@ -13556,7 +13645,7 @@ var SEVERITY_ORDER = {
|
|
|
13556
13645
|
};
|
|
13557
13646
|
function isCodacyAvailable() {
|
|
13558
13647
|
try {
|
|
13559
|
-
(0,
|
|
13648
|
+
(0, import_node_child_process7.execSync)("which codacy-analysis", { stdio: "pipe" });
|
|
13560
13649
|
return true;
|
|
13561
13650
|
} catch {
|
|
13562
13651
|
return false;
|
|
@@ -13580,7 +13669,7 @@ function runCodacyAnalysis(files) {
|
|
|
13580
13669
|
const fileArgs = existingFiles.join(" ");
|
|
13581
13670
|
let output;
|
|
13582
13671
|
try {
|
|
13583
|
-
output = (0,
|
|
13672
|
+
output = (0, import_node_child_process7.execSync)(
|
|
13584
13673
|
`codacy-analysis analyze --install-dependencies --files ${fileArgs} --output-format json --log-level error --parallel-tools 3`,
|
|
13585
13674
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], maxBuffer: 10 * 1024 * 1024 }
|
|
13586
13675
|
);
|
|
@@ -13634,7 +13723,7 @@ function runCodacyAnalysis(files) {
|
|
|
13634
13723
|
|
|
13635
13724
|
// src/lib/specs.ts
|
|
13636
13725
|
var import_node_fs11 = require("node:fs");
|
|
13637
|
-
var
|
|
13726
|
+
var import_node_path11 = require("node:path");
|
|
13638
13727
|
var SPEC_CANDIDATES = [
|
|
13639
13728
|
"CLAUDE.md",
|
|
13640
13729
|
"AGENTS.md",
|
|
@@ -13696,7 +13785,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
13696
13785
|
try {
|
|
13697
13786
|
const entries = (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true });
|
|
13698
13787
|
for (const entry of entries) {
|
|
13699
|
-
const fullPath = (0,
|
|
13788
|
+
const fullPath = (0, import_node_path11.join)(dir, entry.name);
|
|
13700
13789
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
13701
13790
|
result.push(fullPath);
|
|
13702
13791
|
} else if (entry.isDirectory() && depth < maxDepth - 1) {
|
|
@@ -13708,7 +13797,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
13708
13797
|
return result;
|
|
13709
13798
|
}
|
|
13710
13799
|
function discoverPlans() {
|
|
13711
|
-
const homePlansDir = (0,
|
|
13800
|
+
const homePlansDir = (0, import_node_path11.join)(process.env.HOME ?? "", ".claude", "plans");
|
|
13712
13801
|
const localPlansDir = ".claude/plans";
|
|
13713
13802
|
const candidates = [];
|
|
13714
13803
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13718,7 +13807,7 @@ function discoverPlans() {
|
|
|
13718
13807
|
for (const f of (0, import_node_fs11.readdirSync)(plansDir)) {
|
|
13719
13808
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
13720
13809
|
seen.add(f);
|
|
13721
|
-
const fullPath = (0,
|
|
13810
|
+
const fullPath = (0, import_node_path11.join)(plansDir, f);
|
|
13722
13811
|
try {
|
|
13723
13812
|
const stat3 = (0, import_node_fs11.statSync)(fullPath);
|
|
13724
13813
|
candidates.push({ name: f, path: fullPath, mtime: stat3.mtimeMs, size: stat3.size });
|
|
@@ -13743,15 +13832,15 @@ function discoverPlans() {
|
|
|
13743
13832
|
|
|
13744
13833
|
// src/lib/snapshot.ts
|
|
13745
13834
|
var import_node_fs12 = require("node:fs");
|
|
13746
|
-
var
|
|
13747
|
-
var
|
|
13835
|
+
var import_node_path12 = require("node:path");
|
|
13836
|
+
var import_node_child_process8 = require("node:child_process");
|
|
13748
13837
|
function generateSnapshotDiffs(files) {
|
|
13749
13838
|
if (!(0, import_node_fs12.existsSync)(SNAPSHOT_DIR)) {
|
|
13750
13839
|
return { diffs: [], has_snapshots: false };
|
|
13751
13840
|
}
|
|
13752
13841
|
const diffs = [];
|
|
13753
13842
|
for (const file of files) {
|
|
13754
|
-
const snapshotPath = (0,
|
|
13843
|
+
const snapshotPath = (0, import_node_path12.join)(SNAPSHOT_DIR, file.path);
|
|
13755
13844
|
const language = file.language ?? detectLanguage(file.path);
|
|
13756
13845
|
if ((0, import_node_fs12.existsSync)(snapshotPath)) {
|
|
13757
13846
|
const oldContent = (0, import_node_fs12.readFileSync)(snapshotPath, "utf-8");
|
|
@@ -13778,21 +13867,21 @@ ${addedLines}`,
|
|
|
13778
13867
|
function saveSnapshots(files) {
|
|
13779
13868
|
const snapshotPaths = /* @__PURE__ */ new Set();
|
|
13780
13869
|
for (const file of files) {
|
|
13781
|
-
const snapshotPath = (0,
|
|
13870
|
+
const snapshotPath = (0, import_node_path12.join)(SNAPSHOT_DIR, file.path);
|
|
13782
13871
|
snapshotPaths.add(snapshotPath);
|
|
13783
|
-
(0, import_node_fs12.mkdirSync)((0,
|
|
13872
|
+
(0, import_node_fs12.mkdirSync)((0, import_node_path12.dirname)(snapshotPath), { recursive: true });
|
|
13784
13873
|
(0, import_node_fs12.writeFileSync)(snapshotPath, file.content);
|
|
13785
13874
|
}
|
|
13786
13875
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
13787
13876
|
}
|
|
13788
13877
|
function computeDiff(oldContent, newContent, filePath) {
|
|
13789
|
-
const tmpOld = (0,
|
|
13790
|
-
const tmpNew = (0,
|
|
13878
|
+
const tmpOld = (0, import_node_path12.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
13879
|
+
const tmpNew = (0, import_node_path12.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
13791
13880
|
try {
|
|
13792
13881
|
(0, import_node_fs12.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
13793
13882
|
(0, import_node_fs12.writeFileSync)(tmpOld, oldContent);
|
|
13794
13883
|
(0, import_node_fs12.writeFileSync)(tmpNew, newContent);
|
|
13795
|
-
const result = (0,
|
|
13884
|
+
const result = (0, import_node_child_process8.execSync)(
|
|
13796
13885
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
13797
13886
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
13798
13887
|
);
|
|
@@ -13820,7 +13909,7 @@ function cleanStaleSnapshots(dir, keepSet) {
|
|
|
13820
13909
|
const entries = (0, import_node_fs12.readdirSync)(dir, { withFileTypes: true });
|
|
13821
13910
|
for (const entry of entries) {
|
|
13822
13911
|
if (entry.name.startsWith(".")) continue;
|
|
13823
|
-
const fullPath = (0,
|
|
13912
|
+
const fullPath = (0, import_node_path12.join)(dir, entry.name);
|
|
13824
13913
|
if (entry.isDirectory()) {
|
|
13825
13914
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
13826
13915
|
try {
|
|
@@ -13841,7 +13930,7 @@ function cleanStaleSnapshots(dir, keepSet) {
|
|
|
13841
13930
|
|
|
13842
13931
|
// src/lib/baseline.ts
|
|
13843
13932
|
var import_node_fs13 = require("node:fs");
|
|
13844
|
-
var
|
|
13933
|
+
var import_node_path13 = require("node:path");
|
|
13845
13934
|
var import_node_crypto5 = require("node:crypto");
|
|
13846
13935
|
var BASELINE_VERSION = 1;
|
|
13847
13936
|
var BASELINE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
@@ -13852,13 +13941,13 @@ function sessionKey(sessionId) {
|
|
|
13852
13941
|
return (0, import_node_crypto5.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
13853
13942
|
}
|
|
13854
13943
|
function sessionDir(key) {
|
|
13855
|
-
return (0,
|
|
13944
|
+
return (0, import_node_path13.join)(projectPath(BASELINE_DIR), key);
|
|
13856
13945
|
}
|
|
13857
13946
|
function manifestPath(dir) {
|
|
13858
|
-
return (0,
|
|
13947
|
+
return (0, import_node_path13.join)(dir, "manifest.json");
|
|
13859
13948
|
}
|
|
13860
13949
|
function mirrorPath(dir, repoRelPath) {
|
|
13861
|
-
return (0,
|
|
13950
|
+
return (0, import_node_path13.join)(dir, "files", repoRelPath);
|
|
13862
13951
|
}
|
|
13863
13952
|
function captureBaseline(opts = {}) {
|
|
13864
13953
|
const key = sessionKey(opts.sessionId);
|
|
@@ -13874,7 +13963,7 @@ function captureBaseline(opts = {}) {
|
|
|
13874
13963
|
(0, import_node_fs13.rmSync)(dir, { recursive: true, force: true });
|
|
13875
13964
|
} catch {
|
|
13876
13965
|
}
|
|
13877
|
-
const filesDir = (0,
|
|
13966
|
+
const filesDir = (0, import_node_path13.join)(dir, "files");
|
|
13878
13967
|
const mirrored = [];
|
|
13879
13968
|
try {
|
|
13880
13969
|
(0, import_node_fs13.mkdirSync)(filesDir, { recursive: true });
|
|
@@ -13884,7 +13973,7 @@ function captureBaseline(opts = {}) {
|
|
|
13884
13973
|
if (content === null) continue;
|
|
13885
13974
|
const dest = mirrorPath(dir, p);
|
|
13886
13975
|
try {
|
|
13887
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
13976
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(dest), { recursive: true });
|
|
13888
13977
|
(0, import_node_fs13.writeFileSync)(dest, content);
|
|
13889
13978
|
mirrored.push(p);
|
|
13890
13979
|
} catch {
|
|
@@ -14012,7 +14101,7 @@ function pruneOldBaselines() {
|
|
|
14012
14101
|
}
|
|
14013
14102
|
const now = Date.now();
|
|
14014
14103
|
for (const name of entries) {
|
|
14015
|
-
const dir = (0,
|
|
14104
|
+
const dir = (0, import_node_path13.join)(root, name);
|
|
14016
14105
|
const manifest = readManifest(dir);
|
|
14017
14106
|
if (!manifest) {
|
|
14018
14107
|
try {
|
|
@@ -14111,7 +14200,7 @@ function gatherContextFiles(contextPaths, deltaFiles) {
|
|
|
14111
14200
|
|
|
14112
14201
|
// src/lib/cache-cleanup.ts
|
|
14113
14202
|
var import_node_fs16 = require("node:fs");
|
|
14114
|
-
var
|
|
14203
|
+
var import_node_path14 = require("node:path");
|
|
14115
14204
|
var CACHE_TTL_DAYS = 7;
|
|
14116
14205
|
function pruneStaleCache() {
|
|
14117
14206
|
try {
|
|
@@ -14119,7 +14208,7 @@ function pruneStaleCache() {
|
|
|
14119
14208
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
14120
14209
|
for (const entry of (0, import_node_fs16.readdirSync)(dir)) {
|
|
14121
14210
|
if (!entry.startsWith("pending-")) continue;
|
|
14122
|
-
const path = (0,
|
|
14211
|
+
const path = (0, import_node_path14.join)(dir, entry);
|
|
14123
14212
|
try {
|
|
14124
14213
|
const stat3 = (0, import_node_fs16.statSync)(path);
|
|
14125
14214
|
if (stat3.mtimeMs < cutoff) {
|
|
@@ -14512,7 +14601,7 @@ function capArray(set, max) {
|
|
|
14512
14601
|
// src/lib/seed-runner.ts
|
|
14513
14602
|
var import_promises12 = require("node:fs/promises");
|
|
14514
14603
|
var import_node_fs18 = require("node:fs");
|
|
14515
|
-
var
|
|
14604
|
+
var import_node_path15 = require("node:path");
|
|
14516
14605
|
var import_yaml2 = __toESM(require_dist());
|
|
14517
14606
|
|
|
14518
14607
|
// src/lib/seed.ts
|
|
@@ -14794,7 +14883,7 @@ async function runSeed(opts) {
|
|
|
14794
14883
|
if (candidates.length === 0) {
|
|
14795
14884
|
return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
|
|
14796
14885
|
}
|
|
14797
|
-
const overviewPath = (0,
|
|
14886
|
+
const overviewPath = (0, import_node_path15.join)(MEMORY_DIR, "domain", "project-overview.md");
|
|
14798
14887
|
if ((0, import_node_fs18.existsSync)(overviewPath) && !opts.force) {
|
|
14799
14888
|
return { created: 0, failed: 0, skipped: "already_seeded", candidates };
|
|
14800
14889
|
}
|
|
@@ -14830,9 +14919,9 @@ async function runSeed(opts) {
|
|
|
14830
14919
|
}
|
|
14831
14920
|
const nodeId = res.data.node_id;
|
|
14832
14921
|
const filePathRel = res.data.file_path;
|
|
14833
|
-
const targetPath = (0,
|
|
14922
|
+
const targetPath = (0, import_node_path15.join)(MEMORY_DIR, filePathRel);
|
|
14834
14923
|
try {
|
|
14835
|
-
await (0, import_promises12.mkdir)((0,
|
|
14924
|
+
await (0, import_promises12.mkdir)((0, import_node_path15.dirname)(targetPath), { recursive: true });
|
|
14836
14925
|
await (0, import_promises12.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
|
|
14837
14926
|
created++;
|
|
14838
14927
|
opts.onCreated?.(nodeId, filePathRel, c);
|
|
@@ -15114,7 +15203,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15114
15203
|
let autoSeedNotice = null;
|
|
15115
15204
|
try {
|
|
15116
15205
|
await ensureMemoryDir();
|
|
15117
|
-
const seedMarker = (0,
|
|
15206
|
+
const seedMarker = (0, import_node_path16.join)(VERITY_DIR, ".seeded");
|
|
15118
15207
|
const hasStandard = (0, import_node_fs19.existsSync)(STANDARD_FILE);
|
|
15119
15208
|
const alreadyTried = (0, import_node_fs19.existsSync)(seedMarker);
|
|
15120
15209
|
if (hasStandard && !alreadyTried) {
|
|
@@ -15348,6 +15437,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15348
15437
|
}
|
|
15349
15438
|
}
|
|
15350
15439
|
saveSnapshots(codeDelta.files.map((f) => ({ path: f.path, content: f.content })));
|
|
15440
|
+
const loginNudge = response.persisted === false ? " \u26A0\uFE0F Not logged in \u2014 this run was NOT saved and Verity has no memory of your project. Run `verity login` to unlock run history, trends, and cloud memory." : "";
|
|
15351
15441
|
switch (decision) {
|
|
15352
15442
|
case "FAIL": {
|
|
15353
15443
|
writeIteration(iteration + 1, currentCommit, contentHash ?? void 0);
|
|
@@ -15420,6 +15510,9 @@ async function runAnalyze(opts, globals) {
|
|
|
15420
15510
|
`);
|
|
15421
15511
|
}
|
|
15422
15512
|
process.stderr.write(`${BOLD}Fix these issues, then I will re-analyze automatically.${NC}
|
|
15513
|
+
`);
|
|
15514
|
+
if (loginNudge) process.stderr.write(`
|
|
15515
|
+
${YELLOW}${loginNudge.trim()}${NC}
|
|
15423
15516
|
`);
|
|
15424
15517
|
process.exit(2);
|
|
15425
15518
|
break;
|
|
@@ -15432,6 +15525,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15432
15525
|
const viewUrl = response.view_url ?? "";
|
|
15433
15526
|
if (viewUrl) userSummary += ` Report: ${viewUrl}`;
|
|
15434
15527
|
if (autoSeedNotice) userSummary = `${autoSeedNotice} ${userSummary}`;
|
|
15528
|
+
userSummary += loginNudge;
|
|
15435
15529
|
printJsonCompact({ gate_decision: "PASS", systemMessage: userSummary });
|
|
15436
15530
|
process.exit(0);
|
|
15437
15531
|
break;
|
|
@@ -15443,12 +15537,13 @@ async function runAnalyze(opts, globals) {
|
|
|
15443
15537
|
const viewUrl = response.view_url ?? "";
|
|
15444
15538
|
if (viewUrl) userSummary += ` Report: ${viewUrl}`;
|
|
15445
15539
|
if (autoSeedNotice) userSummary = `${autoSeedNotice} ${userSummary}`;
|
|
15540
|
+
userSummary += loginNudge;
|
|
15446
15541
|
printJsonCompact({ gate_decision: "WARN", systemMessage: userSummary });
|
|
15447
15542
|
process.exit(0);
|
|
15448
15543
|
break;
|
|
15449
15544
|
}
|
|
15450
15545
|
default: {
|
|
15451
|
-
const msg = autoSeedNotice ? `${autoSeedNotice} Verity: Analysis complete` : "Verity: Analysis complete";
|
|
15546
|
+
const msg = (autoSeedNotice ? `${autoSeedNotice} Verity: Analysis complete` : "Verity: Analysis complete") + loginNudge;
|
|
15452
15547
|
printJsonCompact({ gate_decision: "PASS", systemMessage: msg });
|
|
15453
15548
|
process.exit(0);
|
|
15454
15549
|
}
|
|
@@ -15608,9 +15703,9 @@ async function runReview(opts, globals) {
|
|
|
15608
15703
|
|
|
15609
15704
|
// src/commands/guard.ts
|
|
15610
15705
|
var import_node_fs22 = require("node:fs");
|
|
15611
|
-
var
|
|
15706
|
+
var import_node_path17 = require("node:path");
|
|
15612
15707
|
var GUARD_BLOCK_CAP = 2;
|
|
15613
|
-
var GUARD_ITER_FILE = (0,
|
|
15708
|
+
var GUARD_ITER_FILE = (0, import_node_path17.join)(VERITY_DIR, ".guard-iteration");
|
|
15614
15709
|
function readPreToolUseStdin() {
|
|
15615
15710
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
15616
15711
|
return new Promise((resolve) => {
|
|
@@ -15926,21 +16021,21 @@ function writeBlockMessage(moment, response) {
|
|
|
15926
16021
|
// src/commands/init.ts
|
|
15927
16022
|
var import_node_fs24 = require("node:fs");
|
|
15928
16023
|
var import_promises13 = require("node:fs/promises");
|
|
15929
|
-
var
|
|
15930
|
-
var
|
|
16024
|
+
var import_node_path19 = require("node:path");
|
|
16025
|
+
var import_node_child_process10 = require("node:child_process");
|
|
15931
16026
|
var readline2 = __toESM(require("node:readline/promises"));
|
|
15932
16027
|
|
|
15933
16028
|
// src/commands/migrate.ts
|
|
15934
16029
|
var import_node_fs23 = require("node:fs");
|
|
15935
|
-
var
|
|
15936
|
-
var
|
|
16030
|
+
var import_node_path18 = require("node:path");
|
|
16031
|
+
var import_node_child_process9 = require("node:child_process");
|
|
15937
16032
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
15938
16033
|
function defaultNpmRemover(pkg) {
|
|
15939
|
-
(0,
|
|
16034
|
+
(0, import_node_child_process9.execSync)(`npm rm -g ${pkg}`, { stdio: "pipe", timeout: 12e4 });
|
|
15940
16035
|
}
|
|
15941
16036
|
function isGitTracked(cwd, relPath) {
|
|
15942
16037
|
try {
|
|
15943
|
-
(0,
|
|
16038
|
+
(0, import_node_child_process9.execSync)(`git ls-files --error-unmatch ${relPath}`, { cwd, stdio: "pipe" });
|
|
15944
16039
|
return true;
|
|
15945
16040
|
} catch {
|
|
15946
16041
|
return false;
|
|
@@ -15948,7 +16043,7 @@ function isGitTracked(cwd, relPath) {
|
|
|
15948
16043
|
}
|
|
15949
16044
|
function isGitRepo(cwd) {
|
|
15950
16045
|
try {
|
|
15951
|
-
(0,
|
|
16046
|
+
(0, import_node_child_process9.execSync)("git rev-parse --is-inside-work-tree", { cwd, stdio: "pipe" });
|
|
15952
16047
|
return true;
|
|
15953
16048
|
} catch {
|
|
15954
16049
|
return false;
|
|
@@ -15968,8 +16063,8 @@ async function runMigration(opts = {}) {
|
|
|
15968
16063
|
return { actions, migrated: actions.length > 0 };
|
|
15969
16064
|
}
|
|
15970
16065
|
function migrateProjectDir(root, actions) {
|
|
15971
|
-
const gateDir = (0,
|
|
15972
|
-
const verityDir = (0,
|
|
16066
|
+
const gateDir = (0, import_node_path18.join)(root, ".gate");
|
|
16067
|
+
const verityDir = (0, import_node_path18.join)(root, ".verity");
|
|
15973
16068
|
if ((0, import_node_fs23.existsSync)(gateDir) && !(0, import_node_fs23.existsSync)(verityDir)) {
|
|
15974
16069
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
15975
16070
|
}
|
|
@@ -15987,7 +16082,7 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
15987
16082
|
);
|
|
15988
16083
|
}
|
|
15989
16084
|
try {
|
|
15990
|
-
(0,
|
|
16085
|
+
(0, import_node_child_process9.execSync)("git mv .gate .verity", { cwd: root, stdio: "pipe" });
|
|
15991
16086
|
actions.push("Moved .gate/ \u2192 .verity/ (git mv, staged)");
|
|
15992
16087
|
moved = true;
|
|
15993
16088
|
} catch {
|
|
@@ -16023,11 +16118,11 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
16023
16118
|
}
|
|
16024
16119
|
function migrateGlobalCredentials(home, actions) {
|
|
16025
16120
|
if (!home) return;
|
|
16026
|
-
const gateCreds = (0,
|
|
16027
|
-
const verityCreds = (0,
|
|
16121
|
+
const gateCreds = (0, import_node_path18.join)(home, ".gate", "credentials");
|
|
16122
|
+
const verityCreds = (0, import_node_path18.join)(home, ".verity", "credentials");
|
|
16028
16123
|
if (!(0, import_node_fs23.existsSync)(gateCreds)) return;
|
|
16029
16124
|
if (!(0, import_node_fs23.existsSync)(verityCreds)) {
|
|
16030
|
-
(0, import_node_fs23.mkdirSync)((0,
|
|
16125
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path18.join)(home, ".verity"), { recursive: true });
|
|
16031
16126
|
moveFile(gateCreds, verityCreds);
|
|
16032
16127
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
16033
16128
|
return;
|
|
@@ -16049,7 +16144,7 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
16049
16144
|
}
|
|
16050
16145
|
}
|
|
16051
16146
|
async function migrateClaudeMd(root, actions) {
|
|
16052
|
-
const claudeMd = (0,
|
|
16147
|
+
const claudeMd = (0, import_node_path18.join)(root, "CLAUDE.md");
|
|
16053
16148
|
const hadLegacyBlock = (0, import_node_fs23.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
16054
16149
|
if (!hadLegacyBlock) return;
|
|
16055
16150
|
try {
|
|
@@ -16060,13 +16155,13 @@ async function migrateClaudeMd(root, actions) {
|
|
|
16060
16155
|
}
|
|
16061
16156
|
}
|
|
16062
16157
|
function migrateStandardFile(root, actions) {
|
|
16063
|
-
const gateMd = (0,
|
|
16064
|
-
const verityMd = (0,
|
|
16158
|
+
const gateMd = (0, import_node_path18.join)(root, "GATE.md");
|
|
16159
|
+
const verityMd = (0, import_node_path18.join)(root, "VERITY.md");
|
|
16065
16160
|
if (!(0, import_node_fs23.existsSync)(gateMd) || (0, import_node_fs23.existsSync)(verityMd)) return;
|
|
16066
16161
|
let moved = false;
|
|
16067
16162
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
16068
16163
|
try {
|
|
16069
|
-
(0,
|
|
16164
|
+
(0, import_node_child_process9.execSync)("git mv GATE.md VERITY.md", { cwd: root, stdio: "pipe" });
|
|
16070
16165
|
moved = true;
|
|
16071
16166
|
} catch {
|
|
16072
16167
|
}
|
|
@@ -16122,7 +16217,7 @@ function readFileSyncSafe(path) {
|
|
|
16122
16217
|
}
|
|
16123
16218
|
function hasStagedChanges(root) {
|
|
16124
16219
|
try {
|
|
16125
|
-
(0,
|
|
16220
|
+
(0, import_node_child_process9.execSync)("git diff --cached --quiet", { cwd: root, stdio: "pipe" });
|
|
16126
16221
|
return false;
|
|
16127
16222
|
} catch {
|
|
16128
16223
|
return true;
|
|
@@ -16149,15 +16244,15 @@ function moveFile(from, to) {
|
|
|
16149
16244
|
function carryLegacyContents(gateDir, verityDir) {
|
|
16150
16245
|
let copied = 0;
|
|
16151
16246
|
const walk = (relDir) => {
|
|
16152
|
-
const srcDir = (0,
|
|
16247
|
+
const srcDir = (0, import_node_path18.join)(gateDir, relDir);
|
|
16153
16248
|
for (const entry of (0, import_node_fs23.readdirSync)(srcDir)) {
|
|
16154
|
-
const rel = relDir ? (0,
|
|
16155
|
-
const src = (0,
|
|
16156
|
-
const dest = (0,
|
|
16249
|
+
const rel = relDir ? (0, import_node_path18.join)(relDir, entry) : entry;
|
|
16250
|
+
const src = (0, import_node_path18.join)(gateDir, rel);
|
|
16251
|
+
const dest = (0, import_node_path18.join)(verityDir, rel);
|
|
16157
16252
|
if ((0, import_node_fs23.statSync)(src).isDirectory()) {
|
|
16158
16253
|
walk(rel);
|
|
16159
16254
|
} else if (!(0, import_node_fs23.existsSync)(dest)) {
|
|
16160
|
-
(0, import_node_fs23.mkdirSync)((0,
|
|
16255
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
|
|
16161
16256
|
(0, import_node_fs23.cpSync)(src, dest);
|
|
16162
16257
|
copied++;
|
|
16163
16258
|
}
|
|
@@ -16167,22 +16262,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
16167
16262
|
return copied;
|
|
16168
16263
|
}
|
|
16169
16264
|
async function needsMigration(root = repoRoot()) {
|
|
16170
|
-
const gateDir = (0,
|
|
16171
|
-
const verityDir = (0,
|
|
16265
|
+
const gateDir = (0, import_node_path18.join)(root, ".gate");
|
|
16266
|
+
const verityDir = (0, import_node_path18.join)(root, ".verity");
|
|
16172
16267
|
if ((0, import_node_fs23.existsSync)(gateDir) && !(0, import_node_fs23.existsSync)(verityDir)) return true;
|
|
16173
16268
|
if ((0, import_node_fs23.existsSync)(gateDir) && (0, import_node_fs23.existsSync)(verityDir)) {
|
|
16174
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16269
|
+
if ((0, import_node_fs23.existsSync)((0, import_node_path18.join)(gateDir, "credentials")) && !(0, import_node_fs23.existsSync)((0, import_node_path18.join)(verityDir, "credentials"))) {
|
|
16175
16270
|
return true;
|
|
16176
16271
|
}
|
|
16177
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16272
|
+
if ((0, import_node_fs23.existsSync)((0, import_node_path18.join)(gateDir, "memory")) && !(0, import_node_fs23.existsSync)((0, import_node_path18.join)(verityDir, "memory"))) {
|
|
16178
16273
|
return true;
|
|
16179
16274
|
}
|
|
16180
16275
|
}
|
|
16181
|
-
const claudeMd = (0,
|
|
16276
|
+
const claudeMd = (0, import_node_path18.join)(root, "CLAUDE.md");
|
|
16182
16277
|
if ((0, import_node_fs23.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
16183
16278
|
return true;
|
|
16184
16279
|
}
|
|
16185
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16280
|
+
if ((0, import_node_fs23.existsSync)((0, import_node_path18.join)(root, "GATE.md")) && !(0, import_node_fs23.existsSync)((0, import_node_path18.join)(root, "VERITY.md"))) {
|
|
16186
16281
|
return true;
|
|
16187
16282
|
}
|
|
16188
16283
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -16218,15 +16313,30 @@ async function promptYes(question) {
|
|
|
16218
16313
|
rl.close();
|
|
16219
16314
|
}
|
|
16220
16315
|
}
|
|
16221
|
-
async function runOptionalAuth() {
|
|
16316
|
+
async function runOptionalAuth(serviceUrl) {
|
|
16222
16317
|
const existing = await resolveToken();
|
|
16223
16318
|
if (existing.ok) {
|
|
16224
|
-
|
|
16225
|
-
|
|
16319
|
+
const who = await whoami(existing.data.token, serviceUrl);
|
|
16320
|
+
if (who.ok && who.data.logged_in) {
|
|
16321
|
+
printInfo(`Logged in as ${who.data.email ?? `user #${who.data.user_id}`} \u2713 \u2014 runs & memory sync to Verity.`);
|
|
16322
|
+
return;
|
|
16323
|
+
}
|
|
16324
|
+
if (!who.ok) {
|
|
16325
|
+
if (existing.data.userId != null) {
|
|
16326
|
+
printInfo(`Logged in as ${existing.data.email ?? `user #${existing.data.userId}`} (cached \u2014 could not reach the Verity service). \u2713`);
|
|
16327
|
+
} else {
|
|
16328
|
+
printInfo("Could not confirm your login state with the service; continuing with your existing token.");
|
|
16329
|
+
}
|
|
16330
|
+
return;
|
|
16331
|
+
}
|
|
16332
|
+
console.log("");
|
|
16333
|
+
printWarn("You are NOT logged in \u2014 this project has only an anonymous token.");
|
|
16334
|
+
printInfo(" The gate still runs, but no runs are saved and Verity keeps no memory of this project.");
|
|
16335
|
+
printInfo(" Log in below to unlock run history, trends, and cloud memory (strongly recommended).");
|
|
16226
16336
|
}
|
|
16227
16337
|
let remote = "";
|
|
16228
16338
|
try {
|
|
16229
|
-
remote = (0,
|
|
16339
|
+
remote = (0, import_node_child_process10.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
16230
16340
|
} catch {
|
|
16231
16341
|
}
|
|
16232
16342
|
const localOnlyNote = () => {
|
|
@@ -16257,12 +16367,12 @@ async function runOptionalAuth() {
|
|
|
16257
16367
|
localOnlyNote();
|
|
16258
16368
|
return;
|
|
16259
16369
|
}
|
|
16260
|
-
const projectName = parseRemote(remote)?.repo ?? (0,
|
|
16370
|
+
const projectName = parseRemote(remote)?.repo ?? (0, import_node_path19.basename)(process.cwd());
|
|
16261
16371
|
printInfo("Authenticating with GitHub\u2026");
|
|
16262
|
-
const result = await registerProject({ projectName, remote, serviceUrl
|
|
16372
|
+
const result = await registerProject({ projectName, remote, serviceUrl });
|
|
16263
16373
|
if (result.ok) {
|
|
16264
|
-
|
|
16265
|
-
|
|
16374
|
+
const who = result.data.email ?? (result.data.userId != null ? `user #${result.data.userId}` : null);
|
|
16375
|
+
printInfo(`Logged in${who ? ` as ${who}` : ""} \u2713 \u2014 runs, history, and cloud memory now sync to Verity.`);
|
|
16266
16376
|
} else {
|
|
16267
16377
|
printWarn(`Authentication did not complete: ${result.error}`);
|
|
16268
16378
|
localOnlyNote();
|
|
@@ -16270,15 +16380,15 @@ async function runOptionalAuth() {
|
|
|
16270
16380
|
}
|
|
16271
16381
|
function resolveDataDir() {
|
|
16272
16382
|
const candidates = [
|
|
16273
|
-
(0,
|
|
16383
|
+
(0, import_node_path19.join)(__dirname, "..", "data"),
|
|
16274
16384
|
// installed: node_modules/@codacy/verity-cli/data
|
|
16275
|
-
(0,
|
|
16385
|
+
(0, import_node_path19.join)(__dirname, "..", "..", "data"),
|
|
16276
16386
|
// edge case: nested resolution
|
|
16277
|
-
(0,
|
|
16387
|
+
(0, import_node_path19.join)(process.cwd(), "cli", "data")
|
|
16278
16388
|
// local dev: running from repo root
|
|
16279
16389
|
];
|
|
16280
16390
|
for (const candidate of candidates) {
|
|
16281
|
-
if ((0, import_node_fs24.existsSync)((0,
|
|
16391
|
+
if ((0, import_node_fs24.existsSync)((0, import_node_path19.join)(candidate, "skills"))) {
|
|
16282
16392
|
return candidate;
|
|
16283
16393
|
}
|
|
16284
16394
|
}
|
|
@@ -16322,30 +16432,30 @@ function registerInitCommand(program2) {
|
|
|
16322
16432
|
}
|
|
16323
16433
|
printInfo(` Node.js ${nodeVersion} \u2713`);
|
|
16324
16434
|
try {
|
|
16325
|
-
const gitVersion = (0,
|
|
16435
|
+
const gitVersion = (0, import_node_child_process10.execSync)("git --version", { encoding: "utf-8" }).trim();
|
|
16326
16436
|
printInfo(` ${gitVersion} \u2713`);
|
|
16327
16437
|
} catch {
|
|
16328
16438
|
printError("git is required but not installed. Install from https://git-scm.com");
|
|
16329
16439
|
process.exit(1);
|
|
16330
16440
|
}
|
|
16331
16441
|
try {
|
|
16332
|
-
(0,
|
|
16442
|
+
(0, import_node_child_process10.execSync)("which claude", { encoding: "utf-8" });
|
|
16333
16443
|
printInfo(" Claude Code \u2713");
|
|
16334
16444
|
} catch {
|
|
16335
16445
|
printWarn(" Claude Code not found \u2014 hooks will be configured but need Claude Code to run.");
|
|
16336
16446
|
}
|
|
16337
16447
|
try {
|
|
16338
|
-
(0,
|
|
16448
|
+
(0, import_node_child_process10.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
|
|
16339
16449
|
printInfo(" @codacy/analysis-cli \u2713");
|
|
16340
16450
|
} catch {
|
|
16341
16451
|
printInfo(" Installing @codacy/analysis-cli...");
|
|
16342
16452
|
try {
|
|
16343
|
-
(0,
|
|
16453
|
+
(0, import_node_child_process10.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
|
|
16344
16454
|
printInfo(" @codacy/analysis-cli installed \u2713");
|
|
16345
16455
|
} catch {
|
|
16346
16456
|
try {
|
|
16347
16457
|
printWarn(" Retrying with sudo...");
|
|
16348
|
-
(0,
|
|
16458
|
+
(0, import_node_child_process10.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
|
|
16349
16459
|
printInfo(" @codacy/analysis-cli installed \u2713");
|
|
16350
16460
|
} catch {
|
|
16351
16461
|
printWarn(" Could not install @codacy/analysis-cli automatically.");
|
|
@@ -16357,20 +16467,20 @@ function registerInitCommand(program2) {
|
|
|
16357
16467
|
console.log("");
|
|
16358
16468
|
printInfo("Installing skills...");
|
|
16359
16469
|
const dataDir = resolveDataDir();
|
|
16360
|
-
const skillsSource = (0,
|
|
16470
|
+
const skillsSource = (0, import_node_path19.join)(dataDir, "skills");
|
|
16361
16471
|
const skillsDest = ".claude/skills";
|
|
16362
16472
|
const skills = ["verity-setup", "verity-analyze", "verity-status", "verity-feedback", "verity-learn", "verity-memory", "verity-insights", "verity-reflect"];
|
|
16363
16473
|
let skillsInstalled = 0;
|
|
16364
16474
|
for (const skill of skills) {
|
|
16365
|
-
const src = (0,
|
|
16366
|
-
const dest = (0,
|
|
16475
|
+
const src = (0, import_node_path19.join)(skillsSource, skill);
|
|
16476
|
+
const dest = (0, import_node_path19.join)(skillsDest, skill);
|
|
16367
16477
|
if (!(0, import_node_fs24.existsSync)(src)) {
|
|
16368
16478
|
printWarn(` Skill data not found: ${skill}`);
|
|
16369
16479
|
continue;
|
|
16370
16480
|
}
|
|
16371
16481
|
if ((0, import_node_fs24.existsSync)(dest) && !force) {
|
|
16372
|
-
const srcSkill = (0,
|
|
16373
|
-
const destSkill = (0,
|
|
16482
|
+
const srcSkill = (0, import_node_path19.join)(src, "SKILL.md");
|
|
16483
|
+
const destSkill = (0, import_node_path19.join)(dest, "SKILL.md");
|
|
16374
16484
|
if ((0, import_node_fs24.existsSync)(destSkill)) {
|
|
16375
16485
|
try {
|
|
16376
16486
|
const srcContent = await (0, import_promises13.readFile)(srcSkill, "utf-8");
|
|
@@ -16408,11 +16518,13 @@ function registerInitCommand(program2) {
|
|
|
16408
16518
|
} catch (err) {
|
|
16409
16519
|
printWarn(` Could not update CLAUDE.md: ${err.message}`);
|
|
16410
16520
|
}
|
|
16411
|
-
const globalVerityDir = (0,
|
|
16521
|
+
const globalVerityDir = (0, import_node_path19.join)(process.env.HOME ?? "", ".verity");
|
|
16412
16522
|
await (0, import_promises13.mkdir)(globalVerityDir, { recursive: true });
|
|
16413
16523
|
console.log("");
|
|
16414
16524
|
try {
|
|
16415
|
-
|
|
16525
|
+
const globals = program2.opts();
|
|
16526
|
+
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
16527
|
+
await runOptionalAuth(urlResult.ok ? urlResult.data : DEFAULT_SERVICE_URL);
|
|
16416
16528
|
} catch (err) {
|
|
16417
16529
|
printWarn(`Authentication step skipped: ${err.message}`);
|
|
16418
16530
|
}
|
|
@@ -16439,7 +16551,7 @@ function registerInitCommand(program2) {
|
|
|
16439
16551
|
|
|
16440
16552
|
// src/commands/uninstall.ts
|
|
16441
16553
|
var import_node_fs25 = require("node:fs");
|
|
16442
|
-
var
|
|
16554
|
+
var import_node_path20 = require("node:path");
|
|
16443
16555
|
var SKILL_NAMES = [
|
|
16444
16556
|
"verity-setup",
|
|
16445
16557
|
"verity-analyze",
|
|
@@ -16458,7 +16570,7 @@ function registerUninstallCommand(program2) {
|
|
|
16458
16570
|
const actions = [];
|
|
16459
16571
|
const skillsRoot = projectPath(".claude/skills");
|
|
16460
16572
|
for (const name of SKILL_NAMES) {
|
|
16461
|
-
const dir = (0,
|
|
16573
|
+
const dir = (0, import_node_path20.join)(skillsRoot, name);
|
|
16462
16574
|
if ((0, import_node_fs25.existsSync)(dir)) {
|
|
16463
16575
|
actions.push({
|
|
16464
16576
|
label: `Remove .claude/skills/${name}/`,
|
|
@@ -16504,7 +16616,7 @@ function registerUninstallCommand(program2) {
|
|
|
16504
16616
|
}
|
|
16505
16617
|
});
|
|
16506
16618
|
const home = process.env.HOME ?? "";
|
|
16507
|
-
const globalVerityDir = (0,
|
|
16619
|
+
const globalVerityDir = (0, import_node_path20.join)(home, ".verity");
|
|
16508
16620
|
if (purgeGlobal && (0, import_node_fs25.existsSync)(globalVerityDir)) {
|
|
16509
16621
|
actions.push({
|
|
16510
16622
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
@@ -16703,7 +16815,7 @@ function registerTaskCommands(program2) {
|
|
|
16703
16815
|
|
|
16704
16816
|
// src/commands/reset.ts
|
|
16705
16817
|
var import_node_fs26 = require("node:fs");
|
|
16706
|
-
var
|
|
16818
|
+
var import_node_path21 = require("node:path");
|
|
16707
16819
|
function registerResetCommand(program2) {
|
|
16708
16820
|
program2.command("reset").description("Close the current task and clear transient state").option("--keep-task", "Only purge caches; leave the current task open").option("--all", "Also purge diagnostic logs (.verity/.logs/)").action(async (opts) => {
|
|
16709
16821
|
const globals = program2.opts();
|
|
@@ -16744,7 +16856,7 @@ function registerResetCommand(program2) {
|
|
|
16744
16856
|
for (const entry of (0, import_node_fs26.readdirSync)(cacheDir)) {
|
|
16745
16857
|
if (entry.startsWith("pending-")) {
|
|
16746
16858
|
try {
|
|
16747
|
-
(0, import_node_fs26.unlinkSync)((0,
|
|
16859
|
+
(0, import_node_fs26.unlinkSync)((0, import_node_path21.join)(cacheDir, entry));
|
|
16748
16860
|
purged++;
|
|
16749
16861
|
} catch {
|
|
16750
16862
|
}
|
|
@@ -16771,7 +16883,7 @@ function registerResetCommand(program2) {
|
|
|
16771
16883
|
if ((0, import_node_fs26.existsSync)(logsDir)) {
|
|
16772
16884
|
for (const entry of (0, import_node_fs26.readdirSync)(logsDir)) {
|
|
16773
16885
|
try {
|
|
16774
|
-
(0, import_node_fs26.unlinkSync)((0,
|
|
16886
|
+
(0, import_node_fs26.unlinkSync)((0, import_node_path21.join)(logsDir, entry));
|
|
16775
16887
|
} catch {
|
|
16776
16888
|
}
|
|
16777
16889
|
}
|
|
@@ -17161,8 +17273,9 @@ function registerTelemetryCommands(program2) {
|
|
|
17161
17273
|
}
|
|
17162
17274
|
|
|
17163
17275
|
// src/cli.ts
|
|
17164
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.27.
|
|
17276
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.27.2").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
|
|
17165
17277
|
registerAuthCommands(program);
|
|
17278
|
+
registerLoginCommand(program);
|
|
17166
17279
|
registerHooksCommands(program);
|
|
17167
17280
|
registerIntentCommands(program);
|
|
17168
17281
|
registerStandardCommands(program);
|