@codacy/verity-cli 0.27.1-experimental.f7b7eba → 0.27.2-experimental.3f072cc
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 +345 -223
- 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) {
|
|
@@ -14242,6 +14331,12 @@ function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPromp
|
|
|
14242
14331
|
}
|
|
14243
14332
|
return "standard";
|
|
14244
14333
|
}
|
|
14334
|
+
function scopeToAuthored(files, actionSummary) {
|
|
14335
|
+
if (!actionSummary) return { files, signal: "no-transcript" };
|
|
14336
|
+
const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
|
|
14337
|
+
if (touched.length === 0) return { files: [], signal: "none-authored" };
|
|
14338
|
+
return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
|
|
14339
|
+
}
|
|
14245
14340
|
function narrowToAgentAuthored(files, actionSummary) {
|
|
14246
14341
|
if (!actionSummary) return files;
|
|
14247
14342
|
const touched = [
|
|
@@ -14512,7 +14607,7 @@ function capArray(set, max) {
|
|
|
14512
14607
|
// src/lib/seed-runner.ts
|
|
14513
14608
|
var import_promises12 = require("node:fs/promises");
|
|
14514
14609
|
var import_node_fs18 = require("node:fs");
|
|
14515
|
-
var
|
|
14610
|
+
var import_node_path15 = require("node:path");
|
|
14516
14611
|
var import_yaml2 = __toESM(require_dist());
|
|
14517
14612
|
|
|
14518
14613
|
// src/lib/seed.ts
|
|
@@ -14794,7 +14889,7 @@ async function runSeed(opts) {
|
|
|
14794
14889
|
if (candidates.length === 0) {
|
|
14795
14890
|
return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
|
|
14796
14891
|
}
|
|
14797
|
-
const overviewPath = (0,
|
|
14892
|
+
const overviewPath = (0, import_node_path15.join)(MEMORY_DIR, "domain", "project-overview.md");
|
|
14798
14893
|
if ((0, import_node_fs18.existsSync)(overviewPath) && !opts.force) {
|
|
14799
14894
|
return { created: 0, failed: 0, skipped: "already_seeded", candidates };
|
|
14800
14895
|
}
|
|
@@ -14830,9 +14925,9 @@ async function runSeed(opts) {
|
|
|
14830
14925
|
}
|
|
14831
14926
|
const nodeId = res.data.node_id;
|
|
14832
14927
|
const filePathRel = res.data.file_path;
|
|
14833
|
-
const targetPath = (0,
|
|
14928
|
+
const targetPath = (0, import_node_path15.join)(MEMORY_DIR, filePathRel);
|
|
14834
14929
|
try {
|
|
14835
|
-
await (0, import_promises12.mkdir)((0,
|
|
14930
|
+
await (0, import_promises12.mkdir)((0, import_node_path15.dirname)(targetPath), { recursive: true });
|
|
14836
14931
|
await (0, import_promises12.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
|
|
14837
14932
|
created++;
|
|
14838
14933
|
opts.onCreated?.(nodeId, filePathRel, c);
|
|
@@ -15049,8 +15144,11 @@ async function runAnalyze(opts, globals) {
|
|
|
15049
15144
|
}
|
|
15050
15145
|
contentHash = hashResult.hash;
|
|
15051
15146
|
if (analysisMode !== "plan") {
|
|
15052
|
-
const
|
|
15053
|
-
|
|
15147
|
+
const scoped = scopeToAuthored(allForReview, actionSummary);
|
|
15148
|
+
if (scoped.signal === "none-authored" && (actionSummary?.subagents ?? 0) === 0) {
|
|
15149
|
+
passAndExit("No agent-authored code this turn \u2014 working-tree changes were not authored by this session");
|
|
15150
|
+
}
|
|
15151
|
+
const baseForReview = scoped.signal === "authored" && scoped.files.length > 0 ? scoped.files : allForReview;
|
|
15054
15152
|
const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
|
|
15055
15153
|
if (!opts.skipStatic && isCodacyAvailable()) {
|
|
15056
15154
|
let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
@@ -15114,7 +15212,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15114
15212
|
let autoSeedNotice = null;
|
|
15115
15213
|
try {
|
|
15116
15214
|
await ensureMemoryDir();
|
|
15117
|
-
const seedMarker = (0,
|
|
15215
|
+
const seedMarker = (0, import_node_path16.join)(VERITY_DIR, ".seeded");
|
|
15118
15216
|
const hasStandard = (0, import_node_fs19.existsSync)(STANDARD_FILE);
|
|
15119
15217
|
const alreadyTried = (0, import_node_fs19.existsSync)(seedMarker);
|
|
15120
15218
|
if (hasStandard && !alreadyTried) {
|
|
@@ -15348,6 +15446,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15348
15446
|
}
|
|
15349
15447
|
}
|
|
15350
15448
|
saveSnapshots(codeDelta.files.map((f) => ({ path: f.path, content: f.content })));
|
|
15449
|
+
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
15450
|
switch (decision) {
|
|
15352
15451
|
case "FAIL": {
|
|
15353
15452
|
writeIteration(iteration + 1, currentCommit, contentHash ?? void 0);
|
|
@@ -15420,6 +15519,9 @@ async function runAnalyze(opts, globals) {
|
|
|
15420
15519
|
`);
|
|
15421
15520
|
}
|
|
15422
15521
|
process.stderr.write(`${BOLD}Fix these issues, then I will re-analyze automatically.${NC}
|
|
15522
|
+
`);
|
|
15523
|
+
if (loginNudge) process.stderr.write(`
|
|
15524
|
+
${YELLOW}${loginNudge.trim()}${NC}
|
|
15423
15525
|
`);
|
|
15424
15526
|
process.exit(2);
|
|
15425
15527
|
break;
|
|
@@ -15432,6 +15534,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15432
15534
|
const viewUrl = response.view_url ?? "";
|
|
15433
15535
|
if (viewUrl) userSummary += ` Report: ${viewUrl}`;
|
|
15434
15536
|
if (autoSeedNotice) userSummary = `${autoSeedNotice} ${userSummary}`;
|
|
15537
|
+
userSummary += loginNudge;
|
|
15435
15538
|
printJsonCompact({ gate_decision: "PASS", systemMessage: userSummary });
|
|
15436
15539
|
process.exit(0);
|
|
15437
15540
|
break;
|
|
@@ -15443,12 +15546,13 @@ async function runAnalyze(opts, globals) {
|
|
|
15443
15546
|
const viewUrl = response.view_url ?? "";
|
|
15444
15547
|
if (viewUrl) userSummary += ` Report: ${viewUrl}`;
|
|
15445
15548
|
if (autoSeedNotice) userSummary = `${autoSeedNotice} ${userSummary}`;
|
|
15549
|
+
userSummary += loginNudge;
|
|
15446
15550
|
printJsonCompact({ gate_decision: "WARN", systemMessage: userSummary });
|
|
15447
15551
|
process.exit(0);
|
|
15448
15552
|
break;
|
|
15449
15553
|
}
|
|
15450
15554
|
default: {
|
|
15451
|
-
const msg = autoSeedNotice ? `${autoSeedNotice} Verity: Analysis complete` : "Verity: Analysis complete";
|
|
15555
|
+
const msg = (autoSeedNotice ? `${autoSeedNotice} Verity: Analysis complete` : "Verity: Analysis complete") + loginNudge;
|
|
15452
15556
|
printJsonCompact({ gate_decision: "PASS", systemMessage: msg });
|
|
15453
15557
|
process.exit(0);
|
|
15454
15558
|
}
|
|
@@ -15608,9 +15712,9 @@ async function runReview(opts, globals) {
|
|
|
15608
15712
|
|
|
15609
15713
|
// src/commands/guard.ts
|
|
15610
15714
|
var import_node_fs22 = require("node:fs");
|
|
15611
|
-
var
|
|
15715
|
+
var import_node_path17 = require("node:path");
|
|
15612
15716
|
var GUARD_BLOCK_CAP = 2;
|
|
15613
|
-
var GUARD_ITER_FILE = (0,
|
|
15717
|
+
var GUARD_ITER_FILE = (0, import_node_path17.join)(VERITY_DIR, ".guard-iteration");
|
|
15614
15718
|
function readPreToolUseStdin() {
|
|
15615
15719
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
15616
15720
|
return new Promise((resolve) => {
|
|
@@ -15926,21 +16030,21 @@ function writeBlockMessage(moment, response) {
|
|
|
15926
16030
|
// src/commands/init.ts
|
|
15927
16031
|
var import_node_fs24 = require("node:fs");
|
|
15928
16032
|
var import_promises13 = require("node:fs/promises");
|
|
15929
|
-
var
|
|
15930
|
-
var
|
|
16033
|
+
var import_node_path19 = require("node:path");
|
|
16034
|
+
var import_node_child_process10 = require("node:child_process");
|
|
15931
16035
|
var readline2 = __toESM(require("node:readline/promises"));
|
|
15932
16036
|
|
|
15933
16037
|
// src/commands/migrate.ts
|
|
15934
16038
|
var import_node_fs23 = require("node:fs");
|
|
15935
|
-
var
|
|
15936
|
-
var
|
|
16039
|
+
var import_node_path18 = require("node:path");
|
|
16040
|
+
var import_node_child_process9 = require("node:child_process");
|
|
15937
16041
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
15938
16042
|
function defaultNpmRemover(pkg) {
|
|
15939
|
-
(0,
|
|
16043
|
+
(0, import_node_child_process9.execSync)(`npm rm -g ${pkg}`, { stdio: "pipe", timeout: 12e4 });
|
|
15940
16044
|
}
|
|
15941
16045
|
function isGitTracked(cwd, relPath) {
|
|
15942
16046
|
try {
|
|
15943
|
-
(0,
|
|
16047
|
+
(0, import_node_child_process9.execSync)(`git ls-files --error-unmatch ${relPath}`, { cwd, stdio: "pipe" });
|
|
15944
16048
|
return true;
|
|
15945
16049
|
} catch {
|
|
15946
16050
|
return false;
|
|
@@ -15948,7 +16052,7 @@ function isGitTracked(cwd, relPath) {
|
|
|
15948
16052
|
}
|
|
15949
16053
|
function isGitRepo(cwd) {
|
|
15950
16054
|
try {
|
|
15951
|
-
(0,
|
|
16055
|
+
(0, import_node_child_process9.execSync)("git rev-parse --is-inside-work-tree", { cwd, stdio: "pipe" });
|
|
15952
16056
|
return true;
|
|
15953
16057
|
} catch {
|
|
15954
16058
|
return false;
|
|
@@ -15968,8 +16072,8 @@ async function runMigration(opts = {}) {
|
|
|
15968
16072
|
return { actions, migrated: actions.length > 0 };
|
|
15969
16073
|
}
|
|
15970
16074
|
function migrateProjectDir(root, actions) {
|
|
15971
|
-
const gateDir = (0,
|
|
15972
|
-
const verityDir = (0,
|
|
16075
|
+
const gateDir = (0, import_node_path18.join)(root, ".gate");
|
|
16076
|
+
const verityDir = (0, import_node_path18.join)(root, ".verity");
|
|
15973
16077
|
if ((0, import_node_fs23.existsSync)(gateDir) && !(0, import_node_fs23.existsSync)(verityDir)) {
|
|
15974
16078
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
15975
16079
|
}
|
|
@@ -15987,7 +16091,7 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
15987
16091
|
);
|
|
15988
16092
|
}
|
|
15989
16093
|
try {
|
|
15990
|
-
(0,
|
|
16094
|
+
(0, import_node_child_process9.execSync)("git mv .gate .verity", { cwd: root, stdio: "pipe" });
|
|
15991
16095
|
actions.push("Moved .gate/ \u2192 .verity/ (git mv, staged)");
|
|
15992
16096
|
moved = true;
|
|
15993
16097
|
} catch {
|
|
@@ -16023,11 +16127,11 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
16023
16127
|
}
|
|
16024
16128
|
function migrateGlobalCredentials(home, actions) {
|
|
16025
16129
|
if (!home) return;
|
|
16026
|
-
const gateCreds = (0,
|
|
16027
|
-
const verityCreds = (0,
|
|
16130
|
+
const gateCreds = (0, import_node_path18.join)(home, ".gate", "credentials");
|
|
16131
|
+
const verityCreds = (0, import_node_path18.join)(home, ".verity", "credentials");
|
|
16028
16132
|
if (!(0, import_node_fs23.existsSync)(gateCreds)) return;
|
|
16029
16133
|
if (!(0, import_node_fs23.existsSync)(verityCreds)) {
|
|
16030
|
-
(0, import_node_fs23.mkdirSync)((0,
|
|
16134
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path18.join)(home, ".verity"), { recursive: true });
|
|
16031
16135
|
moveFile(gateCreds, verityCreds);
|
|
16032
16136
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
16033
16137
|
return;
|
|
@@ -16049,7 +16153,7 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
16049
16153
|
}
|
|
16050
16154
|
}
|
|
16051
16155
|
async function migrateClaudeMd(root, actions) {
|
|
16052
|
-
const claudeMd = (0,
|
|
16156
|
+
const claudeMd = (0, import_node_path18.join)(root, "CLAUDE.md");
|
|
16053
16157
|
const hadLegacyBlock = (0, import_node_fs23.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
16054
16158
|
if (!hadLegacyBlock) return;
|
|
16055
16159
|
try {
|
|
@@ -16060,13 +16164,13 @@ async function migrateClaudeMd(root, actions) {
|
|
|
16060
16164
|
}
|
|
16061
16165
|
}
|
|
16062
16166
|
function migrateStandardFile(root, actions) {
|
|
16063
|
-
const gateMd = (0,
|
|
16064
|
-
const verityMd = (0,
|
|
16167
|
+
const gateMd = (0, import_node_path18.join)(root, "GATE.md");
|
|
16168
|
+
const verityMd = (0, import_node_path18.join)(root, "VERITY.md");
|
|
16065
16169
|
if (!(0, import_node_fs23.existsSync)(gateMd) || (0, import_node_fs23.existsSync)(verityMd)) return;
|
|
16066
16170
|
let moved = false;
|
|
16067
16171
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
16068
16172
|
try {
|
|
16069
|
-
(0,
|
|
16173
|
+
(0, import_node_child_process9.execSync)("git mv GATE.md VERITY.md", { cwd: root, stdio: "pipe" });
|
|
16070
16174
|
moved = true;
|
|
16071
16175
|
} catch {
|
|
16072
16176
|
}
|
|
@@ -16122,7 +16226,7 @@ function readFileSyncSafe(path) {
|
|
|
16122
16226
|
}
|
|
16123
16227
|
function hasStagedChanges(root) {
|
|
16124
16228
|
try {
|
|
16125
|
-
(0,
|
|
16229
|
+
(0, import_node_child_process9.execSync)("git diff --cached --quiet", { cwd: root, stdio: "pipe" });
|
|
16126
16230
|
return false;
|
|
16127
16231
|
} catch {
|
|
16128
16232
|
return true;
|
|
@@ -16149,15 +16253,15 @@ function moveFile(from, to) {
|
|
|
16149
16253
|
function carryLegacyContents(gateDir, verityDir) {
|
|
16150
16254
|
let copied = 0;
|
|
16151
16255
|
const walk = (relDir) => {
|
|
16152
|
-
const srcDir = (0,
|
|
16256
|
+
const srcDir = (0, import_node_path18.join)(gateDir, relDir);
|
|
16153
16257
|
for (const entry of (0, import_node_fs23.readdirSync)(srcDir)) {
|
|
16154
|
-
const rel = relDir ? (0,
|
|
16155
|
-
const src = (0,
|
|
16156
|
-
const dest = (0,
|
|
16258
|
+
const rel = relDir ? (0, import_node_path18.join)(relDir, entry) : entry;
|
|
16259
|
+
const src = (0, import_node_path18.join)(gateDir, rel);
|
|
16260
|
+
const dest = (0, import_node_path18.join)(verityDir, rel);
|
|
16157
16261
|
if ((0, import_node_fs23.statSync)(src).isDirectory()) {
|
|
16158
16262
|
walk(rel);
|
|
16159
16263
|
} else if (!(0, import_node_fs23.existsSync)(dest)) {
|
|
16160
|
-
(0, import_node_fs23.mkdirSync)((0,
|
|
16264
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
|
|
16161
16265
|
(0, import_node_fs23.cpSync)(src, dest);
|
|
16162
16266
|
copied++;
|
|
16163
16267
|
}
|
|
@@ -16167,22 +16271,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
16167
16271
|
return copied;
|
|
16168
16272
|
}
|
|
16169
16273
|
async function needsMigration(root = repoRoot()) {
|
|
16170
|
-
const gateDir = (0,
|
|
16171
|
-
const verityDir = (0,
|
|
16274
|
+
const gateDir = (0, import_node_path18.join)(root, ".gate");
|
|
16275
|
+
const verityDir = (0, import_node_path18.join)(root, ".verity");
|
|
16172
16276
|
if ((0, import_node_fs23.existsSync)(gateDir) && !(0, import_node_fs23.existsSync)(verityDir)) return true;
|
|
16173
16277
|
if ((0, import_node_fs23.existsSync)(gateDir) && (0, import_node_fs23.existsSync)(verityDir)) {
|
|
16174
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16278
|
+
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
16279
|
return true;
|
|
16176
16280
|
}
|
|
16177
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16281
|
+
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
16282
|
return true;
|
|
16179
16283
|
}
|
|
16180
16284
|
}
|
|
16181
|
-
const claudeMd = (0,
|
|
16285
|
+
const claudeMd = (0, import_node_path18.join)(root, "CLAUDE.md");
|
|
16182
16286
|
if ((0, import_node_fs23.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
16183
16287
|
return true;
|
|
16184
16288
|
}
|
|
16185
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16289
|
+
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
16290
|
return true;
|
|
16187
16291
|
}
|
|
16188
16292
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -16218,15 +16322,30 @@ async function promptYes(question) {
|
|
|
16218
16322
|
rl.close();
|
|
16219
16323
|
}
|
|
16220
16324
|
}
|
|
16221
|
-
async function runOptionalAuth() {
|
|
16325
|
+
async function runOptionalAuth(serviceUrl) {
|
|
16222
16326
|
const existing = await resolveToken();
|
|
16223
16327
|
if (existing.ok) {
|
|
16224
|
-
|
|
16225
|
-
|
|
16328
|
+
const who = await whoami(existing.data.token, serviceUrl);
|
|
16329
|
+
if (who.ok && who.data.logged_in) {
|
|
16330
|
+
printInfo(`Logged in as ${who.data.email ?? `user #${who.data.user_id}`} \u2713 \u2014 runs & memory sync to Verity.`);
|
|
16331
|
+
return;
|
|
16332
|
+
}
|
|
16333
|
+
if (!who.ok) {
|
|
16334
|
+
if (existing.data.userId != null) {
|
|
16335
|
+
printInfo(`Logged in as ${existing.data.email ?? `user #${existing.data.userId}`} (cached \u2014 could not reach the Verity service). \u2713`);
|
|
16336
|
+
} else {
|
|
16337
|
+
printInfo("Could not confirm your login state with the service; continuing with your existing token.");
|
|
16338
|
+
}
|
|
16339
|
+
return;
|
|
16340
|
+
}
|
|
16341
|
+
console.log("");
|
|
16342
|
+
printWarn("You are NOT logged in \u2014 this project has only an anonymous token.");
|
|
16343
|
+
printInfo(" The gate still runs, but no runs are saved and Verity keeps no memory of this project.");
|
|
16344
|
+
printInfo(" Log in below to unlock run history, trends, and cloud memory (strongly recommended).");
|
|
16226
16345
|
}
|
|
16227
16346
|
let remote = "";
|
|
16228
16347
|
try {
|
|
16229
|
-
remote = (0,
|
|
16348
|
+
remote = (0, import_node_child_process10.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
16230
16349
|
} catch {
|
|
16231
16350
|
}
|
|
16232
16351
|
const localOnlyNote = () => {
|
|
@@ -16257,12 +16376,12 @@ async function runOptionalAuth() {
|
|
|
16257
16376
|
localOnlyNote();
|
|
16258
16377
|
return;
|
|
16259
16378
|
}
|
|
16260
|
-
const projectName = parseRemote(remote)?.repo ?? (0,
|
|
16379
|
+
const projectName = parseRemote(remote)?.repo ?? (0, import_node_path19.basename)(process.cwd());
|
|
16261
16380
|
printInfo("Authenticating with GitHub\u2026");
|
|
16262
|
-
const result = await registerProject({ projectName, remote, serviceUrl
|
|
16381
|
+
const result = await registerProject({ projectName, remote, serviceUrl });
|
|
16263
16382
|
if (result.ok) {
|
|
16264
|
-
|
|
16265
|
-
|
|
16383
|
+
const who = result.data.email ?? (result.data.userId != null ? `user #${result.data.userId}` : null);
|
|
16384
|
+
printInfo(`Logged in${who ? ` as ${who}` : ""} \u2713 \u2014 runs, history, and cloud memory now sync to Verity.`);
|
|
16266
16385
|
} else {
|
|
16267
16386
|
printWarn(`Authentication did not complete: ${result.error}`);
|
|
16268
16387
|
localOnlyNote();
|
|
@@ -16270,15 +16389,15 @@ async function runOptionalAuth() {
|
|
|
16270
16389
|
}
|
|
16271
16390
|
function resolveDataDir() {
|
|
16272
16391
|
const candidates = [
|
|
16273
|
-
(0,
|
|
16392
|
+
(0, import_node_path19.join)(__dirname, "..", "data"),
|
|
16274
16393
|
// installed: node_modules/@codacy/verity-cli/data
|
|
16275
|
-
(0,
|
|
16394
|
+
(0, import_node_path19.join)(__dirname, "..", "..", "data"),
|
|
16276
16395
|
// edge case: nested resolution
|
|
16277
|
-
(0,
|
|
16396
|
+
(0, import_node_path19.join)(process.cwd(), "cli", "data")
|
|
16278
16397
|
// local dev: running from repo root
|
|
16279
16398
|
];
|
|
16280
16399
|
for (const candidate of candidates) {
|
|
16281
|
-
if ((0, import_node_fs24.existsSync)((0,
|
|
16400
|
+
if ((0, import_node_fs24.existsSync)((0, import_node_path19.join)(candidate, "skills"))) {
|
|
16282
16401
|
return candidate;
|
|
16283
16402
|
}
|
|
16284
16403
|
}
|
|
@@ -16322,30 +16441,30 @@ function registerInitCommand(program2) {
|
|
|
16322
16441
|
}
|
|
16323
16442
|
printInfo(` Node.js ${nodeVersion} \u2713`);
|
|
16324
16443
|
try {
|
|
16325
|
-
const gitVersion = (0,
|
|
16444
|
+
const gitVersion = (0, import_node_child_process10.execSync)("git --version", { encoding: "utf-8" }).trim();
|
|
16326
16445
|
printInfo(` ${gitVersion} \u2713`);
|
|
16327
16446
|
} catch {
|
|
16328
16447
|
printError("git is required but not installed. Install from https://git-scm.com");
|
|
16329
16448
|
process.exit(1);
|
|
16330
16449
|
}
|
|
16331
16450
|
try {
|
|
16332
|
-
(0,
|
|
16451
|
+
(0, import_node_child_process10.execSync)("which claude", { encoding: "utf-8" });
|
|
16333
16452
|
printInfo(" Claude Code \u2713");
|
|
16334
16453
|
} catch {
|
|
16335
16454
|
printWarn(" Claude Code not found \u2014 hooks will be configured but need Claude Code to run.");
|
|
16336
16455
|
}
|
|
16337
16456
|
try {
|
|
16338
|
-
(0,
|
|
16457
|
+
(0, import_node_child_process10.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
|
|
16339
16458
|
printInfo(" @codacy/analysis-cli \u2713");
|
|
16340
16459
|
} catch {
|
|
16341
16460
|
printInfo(" Installing @codacy/analysis-cli...");
|
|
16342
16461
|
try {
|
|
16343
|
-
(0,
|
|
16462
|
+
(0, import_node_child_process10.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
|
|
16344
16463
|
printInfo(" @codacy/analysis-cli installed \u2713");
|
|
16345
16464
|
} catch {
|
|
16346
16465
|
try {
|
|
16347
16466
|
printWarn(" Retrying with sudo...");
|
|
16348
|
-
(0,
|
|
16467
|
+
(0, import_node_child_process10.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
|
|
16349
16468
|
printInfo(" @codacy/analysis-cli installed \u2713");
|
|
16350
16469
|
} catch {
|
|
16351
16470
|
printWarn(" Could not install @codacy/analysis-cli automatically.");
|
|
@@ -16357,20 +16476,20 @@ function registerInitCommand(program2) {
|
|
|
16357
16476
|
console.log("");
|
|
16358
16477
|
printInfo("Installing skills...");
|
|
16359
16478
|
const dataDir = resolveDataDir();
|
|
16360
|
-
const skillsSource = (0,
|
|
16479
|
+
const skillsSource = (0, import_node_path19.join)(dataDir, "skills");
|
|
16361
16480
|
const skillsDest = ".claude/skills";
|
|
16362
16481
|
const skills = ["verity-setup", "verity-analyze", "verity-status", "verity-feedback", "verity-learn", "verity-memory", "verity-insights", "verity-reflect"];
|
|
16363
16482
|
let skillsInstalled = 0;
|
|
16364
16483
|
for (const skill of skills) {
|
|
16365
|
-
const src = (0,
|
|
16366
|
-
const dest = (0,
|
|
16484
|
+
const src = (0, import_node_path19.join)(skillsSource, skill);
|
|
16485
|
+
const dest = (0, import_node_path19.join)(skillsDest, skill);
|
|
16367
16486
|
if (!(0, import_node_fs24.existsSync)(src)) {
|
|
16368
16487
|
printWarn(` Skill data not found: ${skill}`);
|
|
16369
16488
|
continue;
|
|
16370
16489
|
}
|
|
16371
16490
|
if ((0, import_node_fs24.existsSync)(dest) && !force) {
|
|
16372
|
-
const srcSkill = (0,
|
|
16373
|
-
const destSkill = (0,
|
|
16491
|
+
const srcSkill = (0, import_node_path19.join)(src, "SKILL.md");
|
|
16492
|
+
const destSkill = (0, import_node_path19.join)(dest, "SKILL.md");
|
|
16374
16493
|
if ((0, import_node_fs24.existsSync)(destSkill)) {
|
|
16375
16494
|
try {
|
|
16376
16495
|
const srcContent = await (0, import_promises13.readFile)(srcSkill, "utf-8");
|
|
@@ -16408,11 +16527,13 @@ function registerInitCommand(program2) {
|
|
|
16408
16527
|
} catch (err) {
|
|
16409
16528
|
printWarn(` Could not update CLAUDE.md: ${err.message}`);
|
|
16410
16529
|
}
|
|
16411
|
-
const globalVerityDir = (0,
|
|
16530
|
+
const globalVerityDir = (0, import_node_path19.join)(process.env.HOME ?? "", ".verity");
|
|
16412
16531
|
await (0, import_promises13.mkdir)(globalVerityDir, { recursive: true });
|
|
16413
16532
|
console.log("");
|
|
16414
16533
|
try {
|
|
16415
|
-
|
|
16534
|
+
const globals = program2.opts();
|
|
16535
|
+
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
16536
|
+
await runOptionalAuth(urlResult.ok ? urlResult.data : DEFAULT_SERVICE_URL);
|
|
16416
16537
|
} catch (err) {
|
|
16417
16538
|
printWarn(`Authentication step skipped: ${err.message}`);
|
|
16418
16539
|
}
|
|
@@ -16439,7 +16560,7 @@ function registerInitCommand(program2) {
|
|
|
16439
16560
|
|
|
16440
16561
|
// src/commands/uninstall.ts
|
|
16441
16562
|
var import_node_fs25 = require("node:fs");
|
|
16442
|
-
var
|
|
16563
|
+
var import_node_path20 = require("node:path");
|
|
16443
16564
|
var SKILL_NAMES = [
|
|
16444
16565
|
"verity-setup",
|
|
16445
16566
|
"verity-analyze",
|
|
@@ -16458,7 +16579,7 @@ function registerUninstallCommand(program2) {
|
|
|
16458
16579
|
const actions = [];
|
|
16459
16580
|
const skillsRoot = projectPath(".claude/skills");
|
|
16460
16581
|
for (const name of SKILL_NAMES) {
|
|
16461
|
-
const dir = (0,
|
|
16582
|
+
const dir = (0, import_node_path20.join)(skillsRoot, name);
|
|
16462
16583
|
if ((0, import_node_fs25.existsSync)(dir)) {
|
|
16463
16584
|
actions.push({
|
|
16464
16585
|
label: `Remove .claude/skills/${name}/`,
|
|
@@ -16504,7 +16625,7 @@ function registerUninstallCommand(program2) {
|
|
|
16504
16625
|
}
|
|
16505
16626
|
});
|
|
16506
16627
|
const home = process.env.HOME ?? "";
|
|
16507
|
-
const globalVerityDir = (0,
|
|
16628
|
+
const globalVerityDir = (0, import_node_path20.join)(home, ".verity");
|
|
16508
16629
|
if (purgeGlobal && (0, import_node_fs25.existsSync)(globalVerityDir)) {
|
|
16509
16630
|
actions.push({
|
|
16510
16631
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
@@ -16703,7 +16824,7 @@ function registerTaskCommands(program2) {
|
|
|
16703
16824
|
|
|
16704
16825
|
// src/commands/reset.ts
|
|
16705
16826
|
var import_node_fs26 = require("node:fs");
|
|
16706
|
-
var
|
|
16827
|
+
var import_node_path21 = require("node:path");
|
|
16707
16828
|
function registerResetCommand(program2) {
|
|
16708
16829
|
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
16830
|
const globals = program2.opts();
|
|
@@ -16744,7 +16865,7 @@ function registerResetCommand(program2) {
|
|
|
16744
16865
|
for (const entry of (0, import_node_fs26.readdirSync)(cacheDir)) {
|
|
16745
16866
|
if (entry.startsWith("pending-")) {
|
|
16746
16867
|
try {
|
|
16747
|
-
(0, import_node_fs26.unlinkSync)((0,
|
|
16868
|
+
(0, import_node_fs26.unlinkSync)((0, import_node_path21.join)(cacheDir, entry));
|
|
16748
16869
|
purged++;
|
|
16749
16870
|
} catch {
|
|
16750
16871
|
}
|
|
@@ -16771,7 +16892,7 @@ function registerResetCommand(program2) {
|
|
|
16771
16892
|
if ((0, import_node_fs26.existsSync)(logsDir)) {
|
|
16772
16893
|
for (const entry of (0, import_node_fs26.readdirSync)(logsDir)) {
|
|
16773
16894
|
try {
|
|
16774
|
-
(0, import_node_fs26.unlinkSync)((0,
|
|
16895
|
+
(0, import_node_fs26.unlinkSync)((0, import_node_path21.join)(logsDir, entry));
|
|
16775
16896
|
} catch {
|
|
16776
16897
|
}
|
|
16777
16898
|
}
|
|
@@ -17161,8 +17282,9 @@ function registerTelemetryCommands(program2) {
|
|
|
17161
17282
|
}
|
|
17162
17283
|
|
|
17163
17284
|
// src/cli.ts
|
|
17164
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.27.
|
|
17285
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.27.2-experimental.3f072cc").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
|
|
17165
17286
|
registerAuthCommands(program);
|
|
17287
|
+
registerLoginCommand(program);
|
|
17166
17288
|
registerHooksCommands(program);
|
|
17167
17289
|
registerIntentCommands(program);
|
|
17168
17290
|
registerStandardCommands(program);
|