@codacy/verity-cli 0.27.1 → 0.27.2-experimental.5fb996a
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 +454 -261
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -10473,7 +10473,7 @@ var SECURITY_PATTERNS = [
|
|
|
10473
10473
|
/Dockerfile/
|
|
10474
10474
|
];
|
|
10475
10475
|
var PROD_SERVICE_URL = "https://ofcamwrjwrkazqvdchko.supabase.co/functions/v1";
|
|
10476
|
-
var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
|
|
10476
|
+
var DEFAULT_SERVICE_URL = "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1".length > 0 ? "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1" : PROD_SERVICE_URL;
|
|
10477
10477
|
var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
|
|
10478
10478
|
var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
|
|
10479
10479
|
var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
@@ -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);
|
|
@@ -11748,12 +11827,12 @@ function registerHooksCommands(program2) {
|
|
|
11748
11827
|
}
|
|
11749
11828
|
|
|
11750
11829
|
// src/commands/intent.ts
|
|
11751
|
-
var
|
|
11830
|
+
var import_node_crypto4 = require("node:crypto");
|
|
11752
11831
|
|
|
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();
|
|
@@ -11867,10 +11946,23 @@ function getRecentCommitMessages() {
|
|
|
11867
11946
|
}
|
|
11868
11947
|
}
|
|
11869
11948
|
|
|
11949
|
+
// src/lib/context-identity.ts
|
|
11950
|
+
var import_node_crypto2 = require("node:crypto");
|
|
11951
|
+
function contextIdentity(token, sessionId) {
|
|
11952
|
+
const t = (token ?? "").trim();
|
|
11953
|
+
const s = (sessionId ?? "").trim();
|
|
11954
|
+
const userKey = t.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
|
|
11955
|
+
const sessionKey2 = s.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
|
|
11956
|
+
return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
|
|
11957
|
+
}
|
|
11958
|
+
function sessionScopeKey(token, sessionId) {
|
|
11959
|
+
return contextIdentity(token, sessionId).bucket;
|
|
11960
|
+
}
|
|
11961
|
+
|
|
11870
11962
|
// src/lib/task-context-buffer.ts
|
|
11871
11963
|
var import_promises7 = require("node:fs/promises");
|
|
11872
11964
|
var import_node_fs4 = require("node:fs");
|
|
11873
|
-
var
|
|
11965
|
+
var import_node_path7 = require("node:path");
|
|
11874
11966
|
var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
|
|
11875
11967
|
var MAX_BUFFER_BYTES = 500 * 1024;
|
|
11876
11968
|
var MAX_PROMPT_CHARS = 2e3;
|
|
@@ -11948,7 +12040,7 @@ async function cleanupTaskContextBuffers() {
|
|
|
11948
12040
|
const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
11949
12041
|
for (const file of files) {
|
|
11950
12042
|
if (!file.endsWith(".jsonl")) continue;
|
|
11951
|
-
const filePath = (0,
|
|
12043
|
+
const filePath = (0, import_node_path7.join)(TASK_CONTEXT_DIR, file);
|
|
11952
12044
|
try {
|
|
11953
12045
|
const stats = await (0, import_promises7.stat)(filePath);
|
|
11954
12046
|
if (stats.mtimeMs < cutoffMs) {
|
|
@@ -11962,7 +12054,7 @@ async function cleanupTaskContextBuffers() {
|
|
|
11962
12054
|
}
|
|
11963
12055
|
function bufferPath(taskId) {
|
|
11964
12056
|
const safe = taskId.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
11965
|
-
return (0,
|
|
12057
|
+
return (0, import_node_path7.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
|
|
11966
12058
|
}
|
|
11967
12059
|
async function appendEntry(taskId, entry) {
|
|
11968
12060
|
try {
|
|
@@ -11988,7 +12080,7 @@ async function appendEntry(taskId, entry) {
|
|
|
11988
12080
|
// src/lib/memory-retrieval.ts
|
|
11989
12081
|
var import_promises8 = require("node:fs/promises");
|
|
11990
12082
|
var import_node_fs5 = require("node:fs");
|
|
11991
|
-
var
|
|
12083
|
+
var import_node_path8 = require("node:path");
|
|
11992
12084
|
var memoryDir = () => projectPath(`${VERITY_DIR}/memory`);
|
|
11993
12085
|
var DOMAINS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
|
|
11994
12086
|
var DEFAULT_BUDGET_TOKENS = 2e3;
|
|
@@ -12086,14 +12178,14 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
12086
12178
|
const promptTokens = tokenize(promptText);
|
|
12087
12179
|
const nodes = [];
|
|
12088
12180
|
for (const domain of DOMAINS) {
|
|
12089
|
-
const domainDir = (0,
|
|
12181
|
+
const domainDir = (0, import_node_path8.join)(memoryDir(), domain);
|
|
12090
12182
|
if (!(0, import_node_fs5.existsSync)(domainDir)) continue;
|
|
12091
12183
|
try {
|
|
12092
12184
|
const files = await (0, import_promises8.readdir)(domainDir);
|
|
12093
12185
|
for (const file of files) {
|
|
12094
12186
|
if (!file.endsWith(".md")) continue;
|
|
12095
12187
|
try {
|
|
12096
|
-
const content = await (0, import_promises8.readFile)((0,
|
|
12188
|
+
const content = await (0, import_promises8.readFile)((0, import_node_path8.join)(domainDir, file), "utf-8");
|
|
12097
12189
|
const { fm, body } = parseFrontmatter(content);
|
|
12098
12190
|
if (fm.status && fm.status !== "active") continue;
|
|
12099
12191
|
nodes.push({
|
|
@@ -12153,8 +12245,8 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
12153
12245
|
// src/lib/memory-sync.ts
|
|
12154
12246
|
var import_promises9 = require("node:fs/promises");
|
|
12155
12247
|
var import_node_fs6 = require("node:fs");
|
|
12156
|
-
var
|
|
12157
|
-
var
|
|
12248
|
+
var import_node_path9 = require("node:path");
|
|
12249
|
+
var import_node_crypto3 = require("node:crypto");
|
|
12158
12250
|
|
|
12159
12251
|
// src/lib/glob-match.ts
|
|
12160
12252
|
function globToRegex(glob) {
|
|
@@ -12224,16 +12316,16 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
|
|
|
12224
12316
|
async function ensureMemoryDir() {
|
|
12225
12317
|
await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
|
|
12226
12318
|
for (const domain of DOMAINS2) {
|
|
12227
|
-
await (0, import_promises9.mkdir)((0,
|
|
12319
|
+
await (0, import_promises9.mkdir)((0, import_node_path9.join)(memoryDir2(), domain), { recursive: true });
|
|
12228
12320
|
}
|
|
12229
|
-
if (!(0, import_node_fs6.existsSync)((0,
|
|
12230
|
-
await (0, import_promises9.writeFile)((0,
|
|
12321
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path9.join)(memoryDir2(), "SCHEMA.md"))) {
|
|
12322
|
+
await (0, import_promises9.writeFile)((0, import_node_path9.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
|
|
12231
12323
|
}
|
|
12232
|
-
if (!(0, import_node_fs6.existsSync)((0,
|
|
12233
|
-
await (0, import_promises9.writeFile)((0,
|
|
12324
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path9.join)(memoryDir2(), "index.md"))) {
|
|
12325
|
+
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
12326
|
}
|
|
12235
|
-
if (!(0, import_node_fs6.existsSync)((0,
|
|
12236
|
-
await (0, import_promises9.writeFile)((0,
|
|
12327
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path9.join)(memoryDir2(), "log.md"))) {
|
|
12328
|
+
await (0, import_promises9.writeFile)((0, import_node_path9.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
|
|
12237
12329
|
}
|
|
12238
12330
|
}
|
|
12239
12331
|
async function buildManifest() {
|
|
@@ -12242,17 +12334,17 @@ async function buildManifest() {
|
|
|
12242
12334
|
}
|
|
12243
12335
|
const nodes = [];
|
|
12244
12336
|
for (const domain of DOMAINS2) {
|
|
12245
|
-
const domainDir = (0,
|
|
12337
|
+
const domainDir = (0, import_node_path9.join)(memoryDir2(), domain);
|
|
12246
12338
|
if (!(0, import_node_fs6.existsSync)(domainDir)) continue;
|
|
12247
12339
|
try {
|
|
12248
12340
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
12249
12341
|
for (const file of files) {
|
|
12250
12342
|
if (!file.endsWith(".md")) continue;
|
|
12251
12343
|
const filePath = `${domain}/${file}`;
|
|
12252
|
-
const fullPath = (0,
|
|
12344
|
+
const fullPath = (0, import_node_path9.join)(memoryDir2(), filePath);
|
|
12253
12345
|
try {
|
|
12254
12346
|
const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
12255
|
-
const hash = (0,
|
|
12347
|
+
const hash = (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
12256
12348
|
nodes.push({ path: filePath, content_hash: `sha256:${hash}` });
|
|
12257
12349
|
} catch {
|
|
12258
12350
|
}
|
|
@@ -12262,32 +12354,32 @@ async function buildManifest() {
|
|
|
12262
12354
|
}
|
|
12263
12355
|
let indexHash = null;
|
|
12264
12356
|
try {
|
|
12265
|
-
const indexContent = await (0, import_promises9.readFile)((0,
|
|
12266
|
-
indexHash = `sha256:${(0,
|
|
12357
|
+
const indexContent = await (0, import_promises9.readFile)((0, import_node_path9.join)(memoryDir2(), "index.md"), "utf-8");
|
|
12358
|
+
indexHash = `sha256:${(0, import_node_crypto3.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
|
|
12267
12359
|
} catch {
|
|
12268
12360
|
}
|
|
12269
12361
|
let logLength = 0;
|
|
12270
12362
|
try {
|
|
12271
|
-
const logContent = await (0, import_promises9.readFile)((0,
|
|
12363
|
+
const logContent = await (0, import_promises9.readFile)((0, import_node_path9.join)(memoryDir2(), "log.md"), "utf-8");
|
|
12272
12364
|
logLength = logContent.split("\n").length;
|
|
12273
12365
|
} catch {
|
|
12274
12366
|
}
|
|
12275
12367
|
return { schema_version: 1, nodes, index_hash: indexHash, log_length: logLength };
|
|
12276
12368
|
}
|
|
12277
12369
|
function hashContent(content) {
|
|
12278
|
-
return `sha256:${(0,
|
|
12370
|
+
return `sha256:${(0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16)}`;
|
|
12279
12371
|
}
|
|
12280
12372
|
async function readOnDiskNodes() {
|
|
12281
12373
|
const out = /* @__PURE__ */ new Map();
|
|
12282
12374
|
if (!(0, import_node_fs6.existsSync)(memoryDir2())) return out;
|
|
12283
12375
|
for (const domain of DOMAINS2) {
|
|
12284
|
-
const domainDir = (0,
|
|
12376
|
+
const domainDir = (0, import_node_path9.join)(memoryDir2(), domain);
|
|
12285
12377
|
if (!(0, import_node_fs6.existsSync)(domainDir)) continue;
|
|
12286
12378
|
try {
|
|
12287
12379
|
for (const file of await (0, import_promises9.readdir)(domainDir)) {
|
|
12288
12380
|
if (!file.endsWith(".md")) continue;
|
|
12289
12381
|
try {
|
|
12290
|
-
out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0,
|
|
12382
|
+
out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path9.join)(domainDir, file), "utf-8")));
|
|
12291
12383
|
} catch {
|
|
12292
12384
|
}
|
|
12293
12385
|
}
|
|
@@ -12333,7 +12425,7 @@ async function computeEditedNodeUploads() {
|
|
|
12333
12425
|
const uploads = [];
|
|
12334
12426
|
for (const [path, prevHash] of prev) {
|
|
12335
12427
|
if (prevHash == null) continue;
|
|
12336
|
-
const full = (0,
|
|
12428
|
+
const full = (0, import_node_path9.join)(memoryDir2(), path);
|
|
12337
12429
|
if (!(0, import_node_fs6.existsSync)(full)) continue;
|
|
12338
12430
|
let content;
|
|
12339
12431
|
try {
|
|
@@ -12370,15 +12462,15 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
12370
12462
|
const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
|
|
12371
12463
|
for (const n of notes) logLines.push(` - ${n}`);
|
|
12372
12464
|
try {
|
|
12373
|
-
const existing = (0, import_node_fs6.existsSync)((0,
|
|
12374
|
-
await (0, import_promises9.writeFile)((0,
|
|
12465
|
+
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";
|
|
12466
|
+
await (0, import_promises9.writeFile)((0, import_node_path9.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
|
|
12375
12467
|
} catch {
|
|
12376
12468
|
}
|
|
12377
12469
|
await recordSyncedNodePaths();
|
|
12378
12470
|
return count;
|
|
12379
12471
|
}
|
|
12380
12472
|
async function applyOneWrite(write, treePaths) {
|
|
12381
|
-
const fullPath = (0,
|
|
12473
|
+
const fullPath = (0, import_node_path9.join)(memoryDir2(), write.path);
|
|
12382
12474
|
const notes = [];
|
|
12383
12475
|
let content = write.content;
|
|
12384
12476
|
if (treePaths && treePaths.length > 0) {
|
|
@@ -12400,7 +12492,7 @@ async function applyOneWrite(write, treePaths) {
|
|
|
12400
12492
|
return { written: false, notes };
|
|
12401
12493
|
}
|
|
12402
12494
|
}
|
|
12403
|
-
await (0, import_promises9.mkdir)((0,
|
|
12495
|
+
await (0, import_promises9.mkdir)((0, import_node_path9.dirname)(fullPath), { recursive: true });
|
|
12404
12496
|
await (0, import_promises9.writeFile)(fullPath, content);
|
|
12405
12497
|
return { written: true, notes };
|
|
12406
12498
|
}
|
|
@@ -12441,7 +12533,7 @@ async function regenerateIndex() {
|
|
|
12441
12533
|
];
|
|
12442
12534
|
let totalNodes = 0;
|
|
12443
12535
|
for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
|
|
12444
|
-
const domainDir = (0,
|
|
12536
|
+
const domainDir = (0, import_node_path9.join)(memoryDir2(), domain);
|
|
12445
12537
|
if (!(0, import_node_fs6.existsSync)(domainDir)) continue;
|
|
12446
12538
|
try {
|
|
12447
12539
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
@@ -12452,7 +12544,7 @@ async function regenerateIndex() {
|
|
|
12452
12544
|
for (const file of mdFiles.sort()) {
|
|
12453
12545
|
const slug = file.replace(/\.md$/, "");
|
|
12454
12546
|
try {
|
|
12455
|
-
const content = await (0, import_promises9.readFile)((0,
|
|
12547
|
+
const content = await (0, import_promises9.readFile)((0, import_node_path9.join)(domainDir, file), "utf-8");
|
|
12456
12548
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
12457
12549
|
const kind = pickFrontmatter(content, "kind") ?? "-";
|
|
12458
12550
|
const confidence = pickFrontmatter(content, "confidence");
|
|
@@ -12476,7 +12568,7 @@ async function regenerateIndex() {
|
|
|
12476
12568
|
lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
|
|
12477
12569
|
}
|
|
12478
12570
|
const next = lines.join("\n") + "\n";
|
|
12479
|
-
const indexPath = (0,
|
|
12571
|
+
const indexPath = (0, import_node_path9.join)(memoryDir2(), "index.md");
|
|
12480
12572
|
let existing = null;
|
|
12481
12573
|
try {
|
|
12482
12574
|
existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
|
|
@@ -12558,7 +12650,7 @@ function hasLegacyMemoryBlock(text) {
|
|
|
12558
12650
|
return findMarker(text, LEGACY_MD_START) !== -1;
|
|
12559
12651
|
}
|
|
12560
12652
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
12561
|
-
const claudeMdPath = (0,
|
|
12653
|
+
const claudeMdPath = (0, import_node_path9.join)(cwd, "CLAUDE.md");
|
|
12562
12654
|
let existing = "";
|
|
12563
12655
|
if ((0, import_node_fs6.existsSync)(claudeMdPath)) {
|
|
12564
12656
|
existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
|
|
@@ -12720,7 +12812,10 @@ function registerIntentCommands(program2) {
|
|
|
12720
12812
|
if (!prompt) {
|
|
12721
12813
|
process.exit(0);
|
|
12722
12814
|
}
|
|
12723
|
-
await
|
|
12815
|
+
const authForScope = await resolveToken(program2.opts().token);
|
|
12816
|
+
const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
|
|
12817
|
+
const scopeSession = event.session_id || process.env.CLAUDE_SESSION_ID || "";
|
|
12818
|
+
await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
|
|
12724
12819
|
try {
|
|
12725
12820
|
await ensureMemoryDir();
|
|
12726
12821
|
const injection = await retrieveForInjection(prompt);
|
|
@@ -12762,7 +12857,7 @@ async function fireClassify(prompt, sessionId) {
|
|
|
12762
12857
|
logEvent("classify_skipped", { reason: "no_service_url", detail: urlResult.error });
|
|
12763
12858
|
return;
|
|
12764
12859
|
}
|
|
12765
|
-
const promptHash = (0,
|
|
12860
|
+
const promptHash = (0, import_node_crypto4.createHash)("sha256").update(prompt).digest("hex");
|
|
12766
12861
|
const result = await apiRequest({
|
|
12767
12862
|
method: "POST",
|
|
12768
12863
|
path: "/classify-task",
|
|
@@ -13113,6 +13208,16 @@ function registerStatusCommand(program2) {
|
|
|
13113
13208
|
return;
|
|
13114
13209
|
}
|
|
13115
13210
|
printInfo("=== Verity Status ===");
|
|
13211
|
+
if (tokenResult.data.userId != null) {
|
|
13212
|
+
printInfo(`Account: Logged in as ${tokenResult.data.email ?? `user #${tokenResult.data.userId}`} \u2713`);
|
|
13213
|
+
} else {
|
|
13214
|
+
const who = await whoami(token, serviceUrl, globals.verbose);
|
|
13215
|
+
if (who.ok && who.data.logged_in) {
|
|
13216
|
+
printInfo(`Account: Logged in as ${who.data.email ?? `user #${who.data.user_id}`} \u2713`);
|
|
13217
|
+
} else if (who.ok && who.data.anonymous) {
|
|
13218
|
+
printInfo('Account: Anonymous \u2014 runs not saved, no cloud memory. Run "verity login".');
|
|
13219
|
+
}
|
|
13220
|
+
}
|
|
13116
13221
|
if (mem.project_name) printInfo(`Project: ${mem.project_name}`);
|
|
13117
13222
|
if (mem.standard) {
|
|
13118
13223
|
const s = mem.standard;
|
|
@@ -13276,11 +13381,11 @@ async function sendGeneralFeedback(message, opts, globals) {
|
|
|
13276
13381
|
|
|
13277
13382
|
// src/commands/analyze.ts
|
|
13278
13383
|
var import_node_fs19 = require("node:fs");
|
|
13279
|
-
var
|
|
13384
|
+
var import_node_path16 = require("node:path");
|
|
13280
13385
|
|
|
13281
13386
|
// src/lib/files.ts
|
|
13282
13387
|
var import_node_fs8 = require("node:fs");
|
|
13283
|
-
var
|
|
13388
|
+
var import_node_path10 = require("node:path");
|
|
13284
13389
|
var LANG_MAP = {
|
|
13285
13390
|
// Analyzable (static analysis + Gemini)
|
|
13286
13391
|
ts: "typescript",
|
|
@@ -13348,7 +13453,7 @@ var LANG_MAP = {
|
|
|
13348
13453
|
mk: "make"
|
|
13349
13454
|
};
|
|
13350
13455
|
function detectLanguage(filepath) {
|
|
13351
|
-
const ext = (0,
|
|
13456
|
+
const ext = (0, import_node_path10.extname)(filepath).slice(1);
|
|
13352
13457
|
return LANG_MAP[ext] ?? ext;
|
|
13353
13458
|
}
|
|
13354
13459
|
function sortByMtime(files) {
|
|
@@ -13410,10 +13515,10 @@ function collectCodeDelta(files, opts) {
|
|
|
13410
13515
|
|
|
13411
13516
|
// src/lib/debounce.ts
|
|
13412
13517
|
var import_node_fs9 = require("node:fs");
|
|
13413
|
-
var
|
|
13518
|
+
var import_node_crypto5 = require("node:crypto");
|
|
13414
13519
|
function scopedFile(base, sessionId) {
|
|
13415
13520
|
if (!sessionId) return base;
|
|
13416
|
-
return `${base}.${(0,
|
|
13521
|
+
return `${base}.${(0, import_node_crypto5.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
|
|
13417
13522
|
}
|
|
13418
13523
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
13419
13524
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
@@ -13454,7 +13559,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
13454
13559
|
return "No files modified since last analysis";
|
|
13455
13560
|
}
|
|
13456
13561
|
function computeContentHash(files) {
|
|
13457
|
-
const hash = (0,
|
|
13562
|
+
const hash = (0, import_node_crypto5.createHash)("sha1");
|
|
13458
13563
|
const sorted = [...files].sort();
|
|
13459
13564
|
for (const f of sorted) {
|
|
13460
13565
|
const resolved = resolveFile(f) ?? f;
|
|
@@ -13543,7 +13648,7 @@ function writeIteration(iteration, commit, _contentHash) {
|
|
|
13543
13648
|
}
|
|
13544
13649
|
|
|
13545
13650
|
// src/lib/static-analysis.ts
|
|
13546
|
-
var
|
|
13651
|
+
var import_node_child_process7 = require("node:child_process");
|
|
13547
13652
|
var import_node_fs10 = require("node:fs");
|
|
13548
13653
|
var SEVERITY_ORDER = {
|
|
13549
13654
|
Error: 0,
|
|
@@ -13556,7 +13661,7 @@ var SEVERITY_ORDER = {
|
|
|
13556
13661
|
};
|
|
13557
13662
|
function isCodacyAvailable() {
|
|
13558
13663
|
try {
|
|
13559
|
-
(0,
|
|
13664
|
+
(0, import_node_child_process7.execSync)("which codacy-analysis", { stdio: "pipe" });
|
|
13560
13665
|
return true;
|
|
13561
13666
|
} catch {
|
|
13562
13667
|
return false;
|
|
@@ -13580,7 +13685,7 @@ function runCodacyAnalysis(files) {
|
|
|
13580
13685
|
const fileArgs = existingFiles.join(" ");
|
|
13581
13686
|
let output;
|
|
13582
13687
|
try {
|
|
13583
|
-
output = (0,
|
|
13688
|
+
output = (0, import_node_child_process7.execSync)(
|
|
13584
13689
|
`codacy-analysis analyze --install-dependencies --files ${fileArgs} --output-format json --log-level error --parallel-tools 3`,
|
|
13585
13690
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], maxBuffer: 10 * 1024 * 1024 }
|
|
13586
13691
|
);
|
|
@@ -13634,7 +13739,7 @@ function runCodacyAnalysis(files) {
|
|
|
13634
13739
|
|
|
13635
13740
|
// src/lib/specs.ts
|
|
13636
13741
|
var import_node_fs11 = require("node:fs");
|
|
13637
|
-
var
|
|
13742
|
+
var import_node_path11 = require("node:path");
|
|
13638
13743
|
var SPEC_CANDIDATES = [
|
|
13639
13744
|
"CLAUDE.md",
|
|
13640
13745
|
"AGENTS.md",
|
|
@@ -13696,7 +13801,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
13696
13801
|
try {
|
|
13697
13802
|
const entries = (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true });
|
|
13698
13803
|
for (const entry of entries) {
|
|
13699
|
-
const fullPath = (0,
|
|
13804
|
+
const fullPath = (0, import_node_path11.join)(dir, entry.name);
|
|
13700
13805
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
13701
13806
|
result.push(fullPath);
|
|
13702
13807
|
} else if (entry.isDirectory() && depth < maxDepth - 1) {
|
|
@@ -13708,7 +13813,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
13708
13813
|
return result;
|
|
13709
13814
|
}
|
|
13710
13815
|
function discoverPlans() {
|
|
13711
|
-
const homePlansDir = (0,
|
|
13816
|
+
const homePlansDir = (0, import_node_path11.join)(process.env.HOME ?? "", ".claude", "plans");
|
|
13712
13817
|
const localPlansDir = ".claude/plans";
|
|
13713
13818
|
const candidates = [];
|
|
13714
13819
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13718,7 +13823,7 @@ function discoverPlans() {
|
|
|
13718
13823
|
for (const f of (0, import_node_fs11.readdirSync)(plansDir)) {
|
|
13719
13824
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
13720
13825
|
seen.add(f);
|
|
13721
|
-
const fullPath = (0,
|
|
13826
|
+
const fullPath = (0, import_node_path11.join)(plansDir, f);
|
|
13722
13827
|
try {
|
|
13723
13828
|
const stat3 = (0, import_node_fs11.statSync)(fullPath);
|
|
13724
13829
|
candidates.push({ name: f, path: fullPath, mtime: stat3.mtimeMs, size: stat3.size });
|
|
@@ -13743,15 +13848,15 @@ function discoverPlans() {
|
|
|
13743
13848
|
|
|
13744
13849
|
// src/lib/snapshot.ts
|
|
13745
13850
|
var import_node_fs12 = require("node:fs");
|
|
13746
|
-
var
|
|
13747
|
-
var
|
|
13851
|
+
var import_node_path12 = require("node:path");
|
|
13852
|
+
var import_node_child_process8 = require("node:child_process");
|
|
13748
13853
|
function generateSnapshotDiffs(files) {
|
|
13749
13854
|
if (!(0, import_node_fs12.existsSync)(SNAPSHOT_DIR)) {
|
|
13750
13855
|
return { diffs: [], has_snapshots: false };
|
|
13751
13856
|
}
|
|
13752
13857
|
const diffs = [];
|
|
13753
13858
|
for (const file of files) {
|
|
13754
|
-
const snapshotPath = (0,
|
|
13859
|
+
const snapshotPath = (0, import_node_path12.join)(SNAPSHOT_DIR, file.path);
|
|
13755
13860
|
const language = file.language ?? detectLanguage(file.path);
|
|
13756
13861
|
if ((0, import_node_fs12.existsSync)(snapshotPath)) {
|
|
13757
13862
|
const oldContent = (0, import_node_fs12.readFileSync)(snapshotPath, "utf-8");
|
|
@@ -13778,21 +13883,21 @@ ${addedLines}`,
|
|
|
13778
13883
|
function saveSnapshots(files) {
|
|
13779
13884
|
const snapshotPaths = /* @__PURE__ */ new Set();
|
|
13780
13885
|
for (const file of files) {
|
|
13781
|
-
const snapshotPath = (0,
|
|
13886
|
+
const snapshotPath = (0, import_node_path12.join)(SNAPSHOT_DIR, file.path);
|
|
13782
13887
|
snapshotPaths.add(snapshotPath);
|
|
13783
|
-
(0, import_node_fs12.mkdirSync)((0,
|
|
13888
|
+
(0, import_node_fs12.mkdirSync)((0, import_node_path12.dirname)(snapshotPath), { recursive: true });
|
|
13784
13889
|
(0, import_node_fs12.writeFileSync)(snapshotPath, file.content);
|
|
13785
13890
|
}
|
|
13786
13891
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
13787
13892
|
}
|
|
13788
13893
|
function computeDiff(oldContent, newContent, filePath) {
|
|
13789
|
-
const tmpOld = (0,
|
|
13790
|
-
const tmpNew = (0,
|
|
13894
|
+
const tmpOld = (0, import_node_path12.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
13895
|
+
const tmpNew = (0, import_node_path12.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
13791
13896
|
try {
|
|
13792
13897
|
(0, import_node_fs12.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
13793
13898
|
(0, import_node_fs12.writeFileSync)(tmpOld, oldContent);
|
|
13794
13899
|
(0, import_node_fs12.writeFileSync)(tmpNew, newContent);
|
|
13795
|
-
const result = (0,
|
|
13900
|
+
const result = (0, import_node_child_process8.execSync)(
|
|
13796
13901
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
13797
13902
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
13798
13903
|
);
|
|
@@ -13820,7 +13925,7 @@ function cleanStaleSnapshots(dir, keepSet) {
|
|
|
13820
13925
|
const entries = (0, import_node_fs12.readdirSync)(dir, { withFileTypes: true });
|
|
13821
13926
|
for (const entry of entries) {
|
|
13822
13927
|
if (entry.name.startsWith(".")) continue;
|
|
13823
|
-
const fullPath = (0,
|
|
13928
|
+
const fullPath = (0, import_node_path12.join)(dir, entry.name);
|
|
13824
13929
|
if (entry.isDirectory()) {
|
|
13825
13930
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
13826
13931
|
try {
|
|
@@ -13841,24 +13946,24 @@ function cleanStaleSnapshots(dir, keepSet) {
|
|
|
13841
13946
|
|
|
13842
13947
|
// src/lib/baseline.ts
|
|
13843
13948
|
var import_node_fs13 = require("node:fs");
|
|
13844
|
-
var
|
|
13845
|
-
var
|
|
13949
|
+
var import_node_path13 = require("node:path");
|
|
13950
|
+
var import_node_crypto6 = require("node:crypto");
|
|
13846
13951
|
var BASELINE_VERSION = 1;
|
|
13847
13952
|
var BASELINE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
13848
13953
|
var MIRROR_MAX_BYTES = 2 * 1024 * 1024;
|
|
13849
13954
|
var DEFAULT_SESSION_KEY = "_default";
|
|
13850
13955
|
function sessionKey(sessionId) {
|
|
13851
13956
|
if (!sessionId) return DEFAULT_SESSION_KEY;
|
|
13852
|
-
return (0,
|
|
13957
|
+
return (0, import_node_crypto6.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
13853
13958
|
}
|
|
13854
13959
|
function sessionDir(key) {
|
|
13855
|
-
return (0,
|
|
13960
|
+
return (0, import_node_path13.join)(projectPath(BASELINE_DIR), key);
|
|
13856
13961
|
}
|
|
13857
13962
|
function manifestPath(dir) {
|
|
13858
|
-
return (0,
|
|
13963
|
+
return (0, import_node_path13.join)(dir, "manifest.json");
|
|
13859
13964
|
}
|
|
13860
13965
|
function mirrorPath(dir, repoRelPath) {
|
|
13861
|
-
return (0,
|
|
13966
|
+
return (0, import_node_path13.join)(dir, "files", repoRelPath);
|
|
13862
13967
|
}
|
|
13863
13968
|
function captureBaseline(opts = {}) {
|
|
13864
13969
|
const key = sessionKey(opts.sessionId);
|
|
@@ -13874,7 +13979,7 @@ function captureBaseline(opts = {}) {
|
|
|
13874
13979
|
(0, import_node_fs13.rmSync)(dir, { recursive: true, force: true });
|
|
13875
13980
|
} catch {
|
|
13876
13981
|
}
|
|
13877
|
-
const filesDir = (0,
|
|
13982
|
+
const filesDir = (0, import_node_path13.join)(dir, "files");
|
|
13878
13983
|
const mirrored = [];
|
|
13879
13984
|
try {
|
|
13880
13985
|
(0, import_node_fs13.mkdirSync)(filesDir, { recursive: true });
|
|
@@ -13884,7 +13989,7 @@ function captureBaseline(opts = {}) {
|
|
|
13884
13989
|
if (content === null) continue;
|
|
13885
13990
|
const dest = mirrorPath(dir, p);
|
|
13886
13991
|
try {
|
|
13887
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
13992
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(dest), { recursive: true });
|
|
13888
13993
|
(0, import_node_fs13.writeFileSync)(dest, content);
|
|
13889
13994
|
mirrored.push(p);
|
|
13890
13995
|
} catch {
|
|
@@ -14012,7 +14117,7 @@ function pruneOldBaselines() {
|
|
|
14012
14117
|
}
|
|
14013
14118
|
const now = Date.now();
|
|
14014
14119
|
for (const name of entries) {
|
|
14015
|
-
const dir = (0,
|
|
14120
|
+
const dir = (0, import_node_path13.join)(root, name);
|
|
14016
14121
|
const manifest = readManifest(dir);
|
|
14017
14122
|
if (!manifest) {
|
|
14018
14123
|
try {
|
|
@@ -14031,13 +14136,75 @@ function pruneOldBaselines() {
|
|
|
14031
14136
|
}
|
|
14032
14137
|
}
|
|
14033
14138
|
|
|
14139
|
+
// src/lib/task-context.ts
|
|
14140
|
+
var import_node_child_process9 = require("node:child_process");
|
|
14141
|
+
var CLOSING_RE = /\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?)\b[\s:]*#(\d+)/i;
|
|
14142
|
+
var BRANCH_RE = /(?:^|[/_-])(?:issue|gh|fix)[-_/]?(\d+)\b/i;
|
|
14143
|
+
function parseLinkedIssue(sources) {
|
|
14144
|
+
for (const c of sources.commits ?? []) {
|
|
14145
|
+
const m = CLOSING_RE.exec(c);
|
|
14146
|
+
if (m) return { issue: parseInt(m[2], 10), via: `commit:${m[1].toLowerCase()}` };
|
|
14147
|
+
}
|
|
14148
|
+
if (sources.branch) {
|
|
14149
|
+
const m = BRANCH_RE.exec(sources.branch);
|
|
14150
|
+
if (m) return { issue: parseInt(m[1], 10), via: "branch" };
|
|
14151
|
+
}
|
|
14152
|
+
return null;
|
|
14153
|
+
}
|
|
14154
|
+
function safeExec(cmd, timeout) {
|
|
14155
|
+
try {
|
|
14156
|
+
return (0, import_node_child_process9.execSync)(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout }).trim();
|
|
14157
|
+
} catch {
|
|
14158
|
+
return "";
|
|
14159
|
+
}
|
|
14160
|
+
}
|
|
14161
|
+
function defaultGhFetch(issue) {
|
|
14162
|
+
const raw = safeExec(`gh issue view ${issue} --json title,body`, 5e3);
|
|
14163
|
+
if (!raw) return null;
|
|
14164
|
+
try {
|
|
14165
|
+
const j = JSON.parse(raw);
|
|
14166
|
+
return j.title ? { title: j.title, body: j.body ?? "" } : null;
|
|
14167
|
+
} catch {
|
|
14168
|
+
return null;
|
|
14169
|
+
}
|
|
14170
|
+
}
|
|
14171
|
+
function resolveTaskContext(opts) {
|
|
14172
|
+
const branch = opts?.branch ?? safeExec("git rev-parse --abbrev-ref HEAD", 3e3);
|
|
14173
|
+
const commits = opts?.commits ?? safeExec("git log -5 --format=%s%n%b", 3e3).split("\n").map((l) => l.trim()).filter(Boolean);
|
|
14174
|
+
const linked = parseLinkedIssue({ branch, commits });
|
|
14175
|
+
if (!linked) return null;
|
|
14176
|
+
const issue = (opts?.ghFetch ?? defaultGhFetch)(linked.issue);
|
|
14177
|
+
if (!issue) return null;
|
|
14178
|
+
const body = (issue.body ?? "").slice(0, 4e3).trim();
|
|
14179
|
+
const goal = `[#${linked.issue}] ${issue.title}${body ? "\n\n" + body : ""}`;
|
|
14180
|
+
return { number: linked.issue, title: issue.title, goal, via: linked.via };
|
|
14181
|
+
}
|
|
14182
|
+
|
|
14183
|
+
// src/lib/run-mode.ts
|
|
14184
|
+
function parseAutonomousEnv(raw) {
|
|
14185
|
+
if (raw === void 0) return void 0;
|
|
14186
|
+
const v = raw.trim().toLowerCase();
|
|
14187
|
+
if (v === "") return void 0;
|
|
14188
|
+
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
14189
|
+
return true;
|
|
14190
|
+
}
|
|
14191
|
+
function resolveRunMode(inputs = {}) {
|
|
14192
|
+
if (inputs.autonomousFlag === true) return "autonomous";
|
|
14193
|
+
if (inputs.autonomousFlag === false) return "interactive";
|
|
14194
|
+
const env = inputs.env ?? process.env;
|
|
14195
|
+
const envDecision = parseAutonomousEnv(env.VERITY_AUTONOMOUS);
|
|
14196
|
+
if (envDecision !== void 0) return envDecision ? "autonomous" : "interactive";
|
|
14197
|
+
const isTTY = inputs.isTTY ?? Boolean(process.stdin?.isTTY);
|
|
14198
|
+
return isTTY ? "interactive" : "autonomous";
|
|
14199
|
+
}
|
|
14200
|
+
|
|
14034
14201
|
// src/lib/offline.ts
|
|
14035
14202
|
var import_node_fs14 = require("node:fs");
|
|
14036
|
-
var
|
|
14203
|
+
var import_node_crypto7 = require("node:crypto");
|
|
14037
14204
|
function cacheRequest(body) {
|
|
14038
14205
|
try {
|
|
14039
14206
|
(0, import_node_fs14.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
14040
|
-
const suffix = (0,
|
|
14207
|
+
const suffix = (0, import_node_crypto7.randomBytes)(4).toString("hex");
|
|
14041
14208
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
14042
14209
|
(0, import_node_fs14.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(body));
|
|
14043
14210
|
} catch {
|
|
@@ -14111,7 +14278,7 @@ function gatherContextFiles(contextPaths, deltaFiles) {
|
|
|
14111
14278
|
|
|
14112
14279
|
// src/lib/cache-cleanup.ts
|
|
14113
14280
|
var import_node_fs16 = require("node:fs");
|
|
14114
|
-
var
|
|
14281
|
+
var import_node_path14 = require("node:path");
|
|
14115
14282
|
var CACHE_TTL_DAYS = 7;
|
|
14116
14283
|
function pruneStaleCache() {
|
|
14117
14284
|
try {
|
|
@@ -14119,7 +14286,7 @@ function pruneStaleCache() {
|
|
|
14119
14286
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
14120
14287
|
for (const entry of (0, import_node_fs16.readdirSync)(dir)) {
|
|
14121
14288
|
if (!entry.startsWith("pending-")) continue;
|
|
14122
|
-
const path = (0,
|
|
14289
|
+
const path = (0, import_node_path14.join)(dir, entry);
|
|
14123
14290
|
try {
|
|
14124
14291
|
const stat3 = (0, import_node_fs16.statSync)(path);
|
|
14125
14292
|
if (stat3.mtimeMs < cutoff) {
|
|
@@ -14242,6 +14409,12 @@ function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPromp
|
|
|
14242
14409
|
}
|
|
14243
14410
|
return "standard";
|
|
14244
14411
|
}
|
|
14412
|
+
function scopeToAuthored(files, actionSummary) {
|
|
14413
|
+
if (!actionSummary) return { files, signal: "no-transcript" };
|
|
14414
|
+
const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
|
|
14415
|
+
if (touched.length === 0) return { files: [], signal: "none-authored" };
|
|
14416
|
+
return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
|
|
14417
|
+
}
|
|
14245
14418
|
function narrowToAgentAuthored(files, actionSummary) {
|
|
14246
14419
|
if (!actionSummary) return files;
|
|
14247
14420
|
const touched = [
|
|
@@ -14512,7 +14685,7 @@ function capArray(set, max) {
|
|
|
14512
14685
|
// src/lib/seed-runner.ts
|
|
14513
14686
|
var import_promises12 = require("node:fs/promises");
|
|
14514
14687
|
var import_node_fs18 = require("node:fs");
|
|
14515
|
-
var
|
|
14688
|
+
var import_node_path15 = require("node:path");
|
|
14516
14689
|
var import_yaml2 = __toESM(require_dist());
|
|
14517
14690
|
|
|
14518
14691
|
// src/lib/seed.ts
|
|
@@ -14794,7 +14967,7 @@ async function runSeed(opts) {
|
|
|
14794
14967
|
if (candidates.length === 0) {
|
|
14795
14968
|
return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
|
|
14796
14969
|
}
|
|
14797
|
-
const overviewPath = (0,
|
|
14970
|
+
const overviewPath = (0, import_node_path15.join)(MEMORY_DIR, "domain", "project-overview.md");
|
|
14798
14971
|
if ((0, import_node_fs18.existsSync)(overviewPath) && !opts.force) {
|
|
14799
14972
|
return { created: 0, failed: 0, skipped: "already_seeded", candidates };
|
|
14800
14973
|
}
|
|
@@ -14830,9 +15003,9 @@ async function runSeed(opts) {
|
|
|
14830
15003
|
}
|
|
14831
15004
|
const nodeId = res.data.node_id;
|
|
14832
15005
|
const filePathRel = res.data.file_path;
|
|
14833
|
-
const targetPath = (0,
|
|
15006
|
+
const targetPath = (0, import_node_path15.join)(MEMORY_DIR, filePathRel);
|
|
14834
15007
|
try {
|
|
14835
|
-
await (0, import_promises12.mkdir)((0,
|
|
15008
|
+
await (0, import_promises12.mkdir)((0, import_node_path15.dirname)(targetPath), { recursive: true });
|
|
14836
15009
|
await (0, import_promises12.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
|
|
14837
15010
|
created++;
|
|
14838
15011
|
opts.onCreated?.(nodeId, filePathRel, c);
|
|
@@ -14923,7 +15096,10 @@ async function runAnalyze(opts, globals) {
|
|
|
14923
15096
|
}
|
|
14924
15097
|
const { assistantMessage: assistantResponse, stopReason, transcriptPath, sessionId } = await readStopHookStdin();
|
|
14925
15098
|
const actionSummary = transcriptPath ? await extractActionSummary(transcriptPath) : null;
|
|
14926
|
-
const
|
|
15099
|
+
const tokenResult = await resolveToken(globals.token);
|
|
15100
|
+
const scopeToken = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
15101
|
+
const rawSessionId = sessionId || process.env.CLAUDE_SESSION_ID || void 0;
|
|
15102
|
+
const baselineSessionId = sessionScopeKey(scopeToken, rawSessionId);
|
|
14927
15103
|
const baseline = readBaseline(baselineSessionId);
|
|
14928
15104
|
if (baseline) {
|
|
14929
15105
|
logEvent("baseline_loaded", {
|
|
@@ -14941,7 +15117,7 @@ async function runAnalyze(opts, globals) {
|
|
|
14941
15117
|
passAndExit("No analyzable files changed");
|
|
14942
15118
|
}
|
|
14943
15119
|
const allForReview = Array.from(/* @__PURE__ */ new Set([...analyzable, ...reviewable]));
|
|
14944
|
-
const conversation = await readAndClearConversationBuffer(
|
|
15120
|
+
const conversation = await readAndClearConversationBuffer(baselineSessionId);
|
|
14945
15121
|
const specs = discoverSpecs();
|
|
14946
15122
|
const plans = discoverPlans();
|
|
14947
15123
|
const latestPrompt = conversation?.prompts?.[conversation.prompts.length - 1]?.prompt ?? "";
|
|
@@ -14955,7 +15131,6 @@ async function runAnalyze(opts, globals) {
|
|
|
14955
15131
|
if (isReflectionQuestion(assistantResponse) && !agentAuthoredCodeThisTurn) {
|
|
14956
15132
|
passAndExit("Reflection-prompt turn \u2014 skipping analysis");
|
|
14957
15133
|
}
|
|
14958
|
-
const tokenResult = await resolveToken(globals.token);
|
|
14959
15134
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
14960
15135
|
if (!tokenResult.ok || !urlResult.ok) {
|
|
14961
15136
|
localOnlyAndExit(runLocalStatic(analyzable, securityFiles, baseline, !!opts.skipStatic));
|
|
@@ -15049,8 +15224,11 @@ async function runAnalyze(opts, globals) {
|
|
|
15049
15224
|
}
|
|
15050
15225
|
contentHash = hashResult.hash;
|
|
15051
15226
|
if (analysisMode !== "plan") {
|
|
15052
|
-
const
|
|
15053
|
-
|
|
15227
|
+
const scoped = scopeToAuthored(allForReview, actionSummary);
|
|
15228
|
+
if (scoped.signal === "none-authored" && (actionSummary?.subagents ?? 0) === 0) {
|
|
15229
|
+
passAndExit("No agent-authored code this turn \u2014 working-tree changes were not authored by this session");
|
|
15230
|
+
}
|
|
15231
|
+
const baseForReview = scoped.signal === "authored" && scoped.files.length > 0 ? scoped.files : allForReview;
|
|
15054
15232
|
const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
|
|
15055
15233
|
if (!opts.skipStatic && isCodacyAvailable()) {
|
|
15056
15234
|
let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
@@ -15114,7 +15292,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15114
15292
|
let autoSeedNotice = null;
|
|
15115
15293
|
try {
|
|
15116
15294
|
await ensureMemoryDir();
|
|
15117
|
-
const seedMarker = (0,
|
|
15295
|
+
const seedMarker = (0, import_node_path16.join)(VERITY_DIR, ".seeded");
|
|
15118
15296
|
const hasStandard = (0, import_node_fs19.existsSync)(STANDARD_FILE);
|
|
15119
15297
|
const alreadyTried = (0, import_node_fs19.existsSync)(seedMarker);
|
|
15120
15298
|
if (hasStandard && !alreadyTried) {
|
|
@@ -15180,7 +15358,9 @@ async function runAnalyze(opts, globals) {
|
|
|
15180
15358
|
if (snapshotResult.has_snapshots && snapshotResult.diffs.length > 0) {
|
|
15181
15359
|
requestBody.snapshot_diffs = snapshotResult.diffs;
|
|
15182
15360
|
}
|
|
15183
|
-
const
|
|
15361
|
+
const noHumanPrompt = (conversation?.prompts?.length ?? 0) === 0;
|
|
15362
|
+
const w4Task = noHumanPrompt && resolveRunMode() === "autonomous" ? resolveTaskContext() : null;
|
|
15363
|
+
const hasIntent = (conversation?.prompts?.length ?? 0) > 0 || specs.length > 0 || plans.length > 0 || !!assistantResponse || !!w4Task;
|
|
15184
15364
|
if (hasIntent) {
|
|
15185
15365
|
const intentContext = {};
|
|
15186
15366
|
if (conversation && conversation.prompts.length > 0) {
|
|
@@ -15195,6 +15375,10 @@ async function runAnalyze(opts, globals) {
|
|
|
15195
15375
|
intentContext.recent_commits = conversation.recent_commits;
|
|
15196
15376
|
}
|
|
15197
15377
|
}
|
|
15378
|
+
if (w4Task && !intentContext.user_prompt) {
|
|
15379
|
+
intentContext.user_prompt = w4Task.goal;
|
|
15380
|
+
logEvent("w4_issue_anchor", { issue: w4Task.number, via: w4Task.via });
|
|
15381
|
+
}
|
|
15198
15382
|
if (assistantResponse) {
|
|
15199
15383
|
const cap = analysisMode === "plan" ? MAX_ASSISTANT_RESPONSE_CHARS_PLAN : MAX_ASSISTANT_RESPONSE_CHARS_DEFAULT;
|
|
15200
15384
|
intentContext.assistant_response = assistantResponse.length > cap ? assistantResponse.slice(0, cap) : assistantResponse;
|
|
@@ -15348,6 +15532,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15348
15532
|
}
|
|
15349
15533
|
}
|
|
15350
15534
|
saveSnapshots(codeDelta.files.map((f) => ({ path: f.path, content: f.content })));
|
|
15535
|
+
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
15536
|
switch (decision) {
|
|
15352
15537
|
case "FAIL": {
|
|
15353
15538
|
writeIteration(iteration + 1, currentCommit, contentHash ?? void 0);
|
|
@@ -15420,6 +15605,9 @@ async function runAnalyze(opts, globals) {
|
|
|
15420
15605
|
`);
|
|
15421
15606
|
}
|
|
15422
15607
|
process.stderr.write(`${BOLD}Fix these issues, then I will re-analyze automatically.${NC}
|
|
15608
|
+
`);
|
|
15609
|
+
if (loginNudge) process.stderr.write(`
|
|
15610
|
+
${YELLOW}${loginNudge.trim()}${NC}
|
|
15423
15611
|
`);
|
|
15424
15612
|
process.exit(2);
|
|
15425
15613
|
break;
|
|
@@ -15432,6 +15620,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15432
15620
|
const viewUrl = response.view_url ?? "";
|
|
15433
15621
|
if (viewUrl) userSummary += ` Report: ${viewUrl}`;
|
|
15434
15622
|
if (autoSeedNotice) userSummary = `${autoSeedNotice} ${userSummary}`;
|
|
15623
|
+
userSummary += loginNudge;
|
|
15435
15624
|
printJsonCompact({ gate_decision: "PASS", systemMessage: userSummary });
|
|
15436
15625
|
process.exit(0);
|
|
15437
15626
|
break;
|
|
@@ -15443,12 +15632,13 @@ async function runAnalyze(opts, globals) {
|
|
|
15443
15632
|
const viewUrl = response.view_url ?? "";
|
|
15444
15633
|
if (viewUrl) userSummary += ` Report: ${viewUrl}`;
|
|
15445
15634
|
if (autoSeedNotice) userSummary = `${autoSeedNotice} ${userSummary}`;
|
|
15635
|
+
userSummary += loginNudge;
|
|
15446
15636
|
printJsonCompact({ gate_decision: "WARN", systemMessage: userSummary });
|
|
15447
15637
|
process.exit(0);
|
|
15448
15638
|
break;
|
|
15449
15639
|
}
|
|
15450
15640
|
default: {
|
|
15451
|
-
const msg = autoSeedNotice ? `${autoSeedNotice} Verity: Analysis complete` : "Verity: Analysis complete";
|
|
15641
|
+
const msg = (autoSeedNotice ? `${autoSeedNotice} Verity: Analysis complete` : "Verity: Analysis complete") + loginNudge;
|
|
15452
15642
|
printJsonCompact({ gate_decision: "PASS", systemMessage: msg });
|
|
15453
15643
|
process.exit(0);
|
|
15454
15644
|
}
|
|
@@ -15481,7 +15671,10 @@ function registerBaselineCommands(program2) {
|
|
|
15481
15671
|
}
|
|
15482
15672
|
}
|
|
15483
15673
|
}
|
|
15484
|
-
const
|
|
15674
|
+
const authForScope = await resolveToken(program2.opts().token);
|
|
15675
|
+
const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
|
|
15676
|
+
const scopeSession = sessionId || process.env.CLAUDE_SESSION_ID || void 0;
|
|
15677
|
+
const result = captureBaseline({ sessionId: sessionScopeKey(scopeToken, scopeSession), source });
|
|
15485
15678
|
logEvent("baseline_capture", {
|
|
15486
15679
|
created: result.created,
|
|
15487
15680
|
source: source ?? null,
|
|
@@ -15608,9 +15801,9 @@ async function runReview(opts, globals) {
|
|
|
15608
15801
|
|
|
15609
15802
|
// src/commands/guard.ts
|
|
15610
15803
|
var import_node_fs22 = require("node:fs");
|
|
15611
|
-
var
|
|
15804
|
+
var import_node_path17 = require("node:path");
|
|
15612
15805
|
var GUARD_BLOCK_CAP = 2;
|
|
15613
|
-
var GUARD_ITER_FILE = (0,
|
|
15806
|
+
var GUARD_ITER_FILE = (0, import_node_path17.join)(VERITY_DIR, ".guard-iteration");
|
|
15614
15807
|
function readPreToolUseStdin() {
|
|
15615
15808
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
15616
15809
|
return new Promise((resolve) => {
|
|
@@ -15926,21 +16119,21 @@ function writeBlockMessage(moment, response) {
|
|
|
15926
16119
|
// src/commands/init.ts
|
|
15927
16120
|
var import_node_fs24 = require("node:fs");
|
|
15928
16121
|
var import_promises13 = require("node:fs/promises");
|
|
15929
|
-
var
|
|
15930
|
-
var
|
|
16122
|
+
var import_node_path19 = require("node:path");
|
|
16123
|
+
var import_node_child_process11 = require("node:child_process");
|
|
15931
16124
|
var readline2 = __toESM(require("node:readline/promises"));
|
|
15932
16125
|
|
|
15933
16126
|
// src/commands/migrate.ts
|
|
15934
16127
|
var import_node_fs23 = require("node:fs");
|
|
15935
|
-
var
|
|
15936
|
-
var
|
|
16128
|
+
var import_node_path18 = require("node:path");
|
|
16129
|
+
var import_node_child_process10 = require("node:child_process");
|
|
15937
16130
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
15938
16131
|
function defaultNpmRemover(pkg) {
|
|
15939
|
-
(0,
|
|
16132
|
+
(0, import_node_child_process10.execSync)(`npm rm -g ${pkg}`, { stdio: "pipe", timeout: 12e4 });
|
|
15940
16133
|
}
|
|
15941
16134
|
function isGitTracked(cwd, relPath) {
|
|
15942
16135
|
try {
|
|
15943
|
-
(0,
|
|
16136
|
+
(0, import_node_child_process10.execSync)(`git ls-files --error-unmatch ${relPath}`, { cwd, stdio: "pipe" });
|
|
15944
16137
|
return true;
|
|
15945
16138
|
} catch {
|
|
15946
16139
|
return false;
|
|
@@ -15948,7 +16141,7 @@ function isGitTracked(cwd, relPath) {
|
|
|
15948
16141
|
}
|
|
15949
16142
|
function isGitRepo(cwd) {
|
|
15950
16143
|
try {
|
|
15951
|
-
(0,
|
|
16144
|
+
(0, import_node_child_process10.execSync)("git rev-parse --is-inside-work-tree", { cwd, stdio: "pipe" });
|
|
15952
16145
|
return true;
|
|
15953
16146
|
} catch {
|
|
15954
16147
|
return false;
|
|
@@ -15968,8 +16161,8 @@ async function runMigration(opts = {}) {
|
|
|
15968
16161
|
return { actions, migrated: actions.length > 0 };
|
|
15969
16162
|
}
|
|
15970
16163
|
function migrateProjectDir(root, actions) {
|
|
15971
|
-
const gateDir = (0,
|
|
15972
|
-
const verityDir = (0,
|
|
16164
|
+
const gateDir = (0, import_node_path18.join)(root, ".gate");
|
|
16165
|
+
const verityDir = (0, import_node_path18.join)(root, ".verity");
|
|
15973
16166
|
if ((0, import_node_fs23.existsSync)(gateDir) && !(0, import_node_fs23.existsSync)(verityDir)) {
|
|
15974
16167
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
15975
16168
|
}
|
|
@@ -15987,7 +16180,7 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
15987
16180
|
);
|
|
15988
16181
|
}
|
|
15989
16182
|
try {
|
|
15990
|
-
(0,
|
|
16183
|
+
(0, import_node_child_process10.execSync)("git mv .gate .verity", { cwd: root, stdio: "pipe" });
|
|
15991
16184
|
actions.push("Moved .gate/ \u2192 .verity/ (git mv, staged)");
|
|
15992
16185
|
moved = true;
|
|
15993
16186
|
} catch {
|
|
@@ -16023,11 +16216,11 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
16023
16216
|
}
|
|
16024
16217
|
function migrateGlobalCredentials(home, actions) {
|
|
16025
16218
|
if (!home) return;
|
|
16026
|
-
const gateCreds = (0,
|
|
16027
|
-
const verityCreds = (0,
|
|
16219
|
+
const gateCreds = (0, import_node_path18.join)(home, ".gate", "credentials");
|
|
16220
|
+
const verityCreds = (0, import_node_path18.join)(home, ".verity", "credentials");
|
|
16028
16221
|
if (!(0, import_node_fs23.existsSync)(gateCreds)) return;
|
|
16029
16222
|
if (!(0, import_node_fs23.existsSync)(verityCreds)) {
|
|
16030
|
-
(0, import_node_fs23.mkdirSync)((0,
|
|
16223
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path18.join)(home, ".verity"), { recursive: true });
|
|
16031
16224
|
moveFile(gateCreds, verityCreds);
|
|
16032
16225
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
16033
16226
|
return;
|
|
@@ -16049,7 +16242,7 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
16049
16242
|
}
|
|
16050
16243
|
}
|
|
16051
16244
|
async function migrateClaudeMd(root, actions) {
|
|
16052
|
-
const claudeMd = (0,
|
|
16245
|
+
const claudeMd = (0, import_node_path18.join)(root, "CLAUDE.md");
|
|
16053
16246
|
const hadLegacyBlock = (0, import_node_fs23.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
16054
16247
|
if (!hadLegacyBlock) return;
|
|
16055
16248
|
try {
|
|
@@ -16060,13 +16253,13 @@ async function migrateClaudeMd(root, actions) {
|
|
|
16060
16253
|
}
|
|
16061
16254
|
}
|
|
16062
16255
|
function migrateStandardFile(root, actions) {
|
|
16063
|
-
const gateMd = (0,
|
|
16064
|
-
const verityMd = (0,
|
|
16256
|
+
const gateMd = (0, import_node_path18.join)(root, "GATE.md");
|
|
16257
|
+
const verityMd = (0, import_node_path18.join)(root, "VERITY.md");
|
|
16065
16258
|
if (!(0, import_node_fs23.existsSync)(gateMd) || (0, import_node_fs23.existsSync)(verityMd)) return;
|
|
16066
16259
|
let moved = false;
|
|
16067
16260
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
16068
16261
|
try {
|
|
16069
|
-
(0,
|
|
16262
|
+
(0, import_node_child_process10.execSync)("git mv GATE.md VERITY.md", { cwd: root, stdio: "pipe" });
|
|
16070
16263
|
moved = true;
|
|
16071
16264
|
} catch {
|
|
16072
16265
|
}
|
|
@@ -16122,7 +16315,7 @@ function readFileSyncSafe(path) {
|
|
|
16122
16315
|
}
|
|
16123
16316
|
function hasStagedChanges(root) {
|
|
16124
16317
|
try {
|
|
16125
|
-
(0,
|
|
16318
|
+
(0, import_node_child_process10.execSync)("git diff --cached --quiet", { cwd: root, stdio: "pipe" });
|
|
16126
16319
|
return false;
|
|
16127
16320
|
} catch {
|
|
16128
16321
|
return true;
|
|
@@ -16149,15 +16342,15 @@ function moveFile(from, to) {
|
|
|
16149
16342
|
function carryLegacyContents(gateDir, verityDir) {
|
|
16150
16343
|
let copied = 0;
|
|
16151
16344
|
const walk = (relDir) => {
|
|
16152
|
-
const srcDir = (0,
|
|
16345
|
+
const srcDir = (0, import_node_path18.join)(gateDir, relDir);
|
|
16153
16346
|
for (const entry of (0, import_node_fs23.readdirSync)(srcDir)) {
|
|
16154
|
-
const rel = relDir ? (0,
|
|
16155
|
-
const src = (0,
|
|
16156
|
-
const dest = (0,
|
|
16347
|
+
const rel = relDir ? (0, import_node_path18.join)(relDir, entry) : entry;
|
|
16348
|
+
const src = (0, import_node_path18.join)(gateDir, rel);
|
|
16349
|
+
const dest = (0, import_node_path18.join)(verityDir, rel);
|
|
16157
16350
|
if ((0, import_node_fs23.statSync)(src).isDirectory()) {
|
|
16158
16351
|
walk(rel);
|
|
16159
16352
|
} else if (!(0, import_node_fs23.existsSync)(dest)) {
|
|
16160
|
-
(0, import_node_fs23.mkdirSync)((0,
|
|
16353
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
|
|
16161
16354
|
(0, import_node_fs23.cpSync)(src, dest);
|
|
16162
16355
|
copied++;
|
|
16163
16356
|
}
|
|
@@ -16167,22 +16360,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
16167
16360
|
return copied;
|
|
16168
16361
|
}
|
|
16169
16362
|
async function needsMigration(root = repoRoot()) {
|
|
16170
|
-
const gateDir = (0,
|
|
16171
|
-
const verityDir = (0,
|
|
16363
|
+
const gateDir = (0, import_node_path18.join)(root, ".gate");
|
|
16364
|
+
const verityDir = (0, import_node_path18.join)(root, ".verity");
|
|
16172
16365
|
if ((0, import_node_fs23.existsSync)(gateDir) && !(0, import_node_fs23.existsSync)(verityDir)) return true;
|
|
16173
16366
|
if ((0, import_node_fs23.existsSync)(gateDir) && (0, import_node_fs23.existsSync)(verityDir)) {
|
|
16174
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16367
|
+
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
16368
|
return true;
|
|
16176
16369
|
}
|
|
16177
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16370
|
+
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
16371
|
return true;
|
|
16179
16372
|
}
|
|
16180
16373
|
}
|
|
16181
|
-
const claudeMd = (0,
|
|
16374
|
+
const claudeMd = (0, import_node_path18.join)(root, "CLAUDE.md");
|
|
16182
16375
|
if ((0, import_node_fs23.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
16183
16376
|
return true;
|
|
16184
16377
|
}
|
|
16185
|
-
if ((0, import_node_fs23.existsSync)((0,
|
|
16378
|
+
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
16379
|
return true;
|
|
16187
16380
|
}
|
|
16188
16381
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -16218,15 +16411,30 @@ async function promptYes(question) {
|
|
|
16218
16411
|
rl.close();
|
|
16219
16412
|
}
|
|
16220
16413
|
}
|
|
16221
|
-
async function runOptionalAuth() {
|
|
16414
|
+
async function runOptionalAuth(serviceUrl) {
|
|
16222
16415
|
const existing = await resolveToken();
|
|
16223
16416
|
if (existing.ok) {
|
|
16224
|
-
|
|
16225
|
-
|
|
16417
|
+
const who = await whoami(existing.data.token, serviceUrl);
|
|
16418
|
+
if (who.ok && who.data.logged_in) {
|
|
16419
|
+
printInfo(`Logged in as ${who.data.email ?? `user #${who.data.user_id}`} \u2713 \u2014 runs & memory sync to Verity.`);
|
|
16420
|
+
return;
|
|
16421
|
+
}
|
|
16422
|
+
if (!who.ok) {
|
|
16423
|
+
if (existing.data.userId != null) {
|
|
16424
|
+
printInfo(`Logged in as ${existing.data.email ?? `user #${existing.data.userId}`} (cached \u2014 could not reach the Verity service). \u2713`);
|
|
16425
|
+
} else {
|
|
16426
|
+
printInfo("Could not confirm your login state with the service; continuing with your existing token.");
|
|
16427
|
+
}
|
|
16428
|
+
return;
|
|
16429
|
+
}
|
|
16430
|
+
console.log("");
|
|
16431
|
+
printWarn("You are NOT logged in \u2014 this project has only an anonymous token.");
|
|
16432
|
+
printInfo(" The gate still runs, but no runs are saved and Verity keeps no memory of this project.");
|
|
16433
|
+
printInfo(" Log in below to unlock run history, trends, and cloud memory (strongly recommended).");
|
|
16226
16434
|
}
|
|
16227
16435
|
let remote = "";
|
|
16228
16436
|
try {
|
|
16229
|
-
remote = (0,
|
|
16437
|
+
remote = (0, import_node_child_process11.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
16230
16438
|
} catch {
|
|
16231
16439
|
}
|
|
16232
16440
|
const localOnlyNote = () => {
|
|
@@ -16257,12 +16465,12 @@ async function runOptionalAuth() {
|
|
|
16257
16465
|
localOnlyNote();
|
|
16258
16466
|
return;
|
|
16259
16467
|
}
|
|
16260
|
-
const projectName = parseRemote(remote)?.repo ?? (0,
|
|
16468
|
+
const projectName = parseRemote(remote)?.repo ?? (0, import_node_path19.basename)(process.cwd());
|
|
16261
16469
|
printInfo("Authenticating with GitHub\u2026");
|
|
16262
|
-
const result = await registerProject({ projectName, remote, serviceUrl
|
|
16470
|
+
const result = await registerProject({ projectName, remote, serviceUrl });
|
|
16263
16471
|
if (result.ok) {
|
|
16264
|
-
|
|
16265
|
-
|
|
16472
|
+
const who = result.data.email ?? (result.data.userId != null ? `user #${result.data.userId}` : null);
|
|
16473
|
+
printInfo(`Logged in${who ? ` as ${who}` : ""} \u2713 \u2014 runs, history, and cloud memory now sync to Verity.`);
|
|
16266
16474
|
} else {
|
|
16267
16475
|
printWarn(`Authentication did not complete: ${result.error}`);
|
|
16268
16476
|
localOnlyNote();
|
|
@@ -16270,15 +16478,15 @@ async function runOptionalAuth() {
|
|
|
16270
16478
|
}
|
|
16271
16479
|
function resolveDataDir() {
|
|
16272
16480
|
const candidates = [
|
|
16273
|
-
(0,
|
|
16481
|
+
(0, import_node_path19.join)(__dirname, "..", "data"),
|
|
16274
16482
|
// installed: node_modules/@codacy/verity-cli/data
|
|
16275
|
-
(0,
|
|
16483
|
+
(0, import_node_path19.join)(__dirname, "..", "..", "data"),
|
|
16276
16484
|
// edge case: nested resolution
|
|
16277
|
-
(0,
|
|
16485
|
+
(0, import_node_path19.join)(process.cwd(), "cli", "data")
|
|
16278
16486
|
// local dev: running from repo root
|
|
16279
16487
|
];
|
|
16280
16488
|
for (const candidate of candidates) {
|
|
16281
|
-
if ((0, import_node_fs24.existsSync)((0,
|
|
16489
|
+
if ((0, import_node_fs24.existsSync)((0, import_node_path19.join)(candidate, "skills"))) {
|
|
16282
16490
|
return candidate;
|
|
16283
16491
|
}
|
|
16284
16492
|
}
|
|
@@ -16322,30 +16530,30 @@ function registerInitCommand(program2) {
|
|
|
16322
16530
|
}
|
|
16323
16531
|
printInfo(` Node.js ${nodeVersion} \u2713`);
|
|
16324
16532
|
try {
|
|
16325
|
-
const gitVersion = (0,
|
|
16533
|
+
const gitVersion = (0, import_node_child_process11.execSync)("git --version", { encoding: "utf-8" }).trim();
|
|
16326
16534
|
printInfo(` ${gitVersion} \u2713`);
|
|
16327
16535
|
} catch {
|
|
16328
16536
|
printError("git is required but not installed. Install from https://git-scm.com");
|
|
16329
16537
|
process.exit(1);
|
|
16330
16538
|
}
|
|
16331
16539
|
try {
|
|
16332
|
-
(0,
|
|
16540
|
+
(0, import_node_child_process11.execSync)("which claude", { encoding: "utf-8" });
|
|
16333
16541
|
printInfo(" Claude Code \u2713");
|
|
16334
16542
|
} catch {
|
|
16335
16543
|
printWarn(" Claude Code not found \u2014 hooks will be configured but need Claude Code to run.");
|
|
16336
16544
|
}
|
|
16337
16545
|
try {
|
|
16338
|
-
(0,
|
|
16546
|
+
(0, import_node_child_process11.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
|
|
16339
16547
|
printInfo(" @codacy/analysis-cli \u2713");
|
|
16340
16548
|
} catch {
|
|
16341
16549
|
printInfo(" Installing @codacy/analysis-cli...");
|
|
16342
16550
|
try {
|
|
16343
|
-
(0,
|
|
16551
|
+
(0, import_node_child_process11.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
|
|
16344
16552
|
printInfo(" @codacy/analysis-cli installed \u2713");
|
|
16345
16553
|
} catch {
|
|
16346
16554
|
try {
|
|
16347
16555
|
printWarn(" Retrying with sudo...");
|
|
16348
|
-
(0,
|
|
16556
|
+
(0, import_node_child_process11.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
|
|
16349
16557
|
printInfo(" @codacy/analysis-cli installed \u2713");
|
|
16350
16558
|
} catch {
|
|
16351
16559
|
printWarn(" Could not install @codacy/analysis-cli automatically.");
|
|
@@ -16357,20 +16565,20 @@ function registerInitCommand(program2) {
|
|
|
16357
16565
|
console.log("");
|
|
16358
16566
|
printInfo("Installing skills...");
|
|
16359
16567
|
const dataDir = resolveDataDir();
|
|
16360
|
-
const skillsSource = (0,
|
|
16568
|
+
const skillsSource = (0, import_node_path19.join)(dataDir, "skills");
|
|
16361
16569
|
const skillsDest = ".claude/skills";
|
|
16362
16570
|
const skills = ["verity-setup", "verity-analyze", "verity-status", "verity-feedback", "verity-learn", "verity-memory", "verity-insights", "verity-reflect"];
|
|
16363
16571
|
let skillsInstalled = 0;
|
|
16364
16572
|
for (const skill of skills) {
|
|
16365
|
-
const src = (0,
|
|
16366
|
-
const dest = (0,
|
|
16573
|
+
const src = (0, import_node_path19.join)(skillsSource, skill);
|
|
16574
|
+
const dest = (0, import_node_path19.join)(skillsDest, skill);
|
|
16367
16575
|
if (!(0, import_node_fs24.existsSync)(src)) {
|
|
16368
16576
|
printWarn(` Skill data not found: ${skill}`);
|
|
16369
16577
|
continue;
|
|
16370
16578
|
}
|
|
16371
16579
|
if ((0, import_node_fs24.existsSync)(dest) && !force) {
|
|
16372
|
-
const srcSkill = (0,
|
|
16373
|
-
const destSkill = (0,
|
|
16580
|
+
const srcSkill = (0, import_node_path19.join)(src, "SKILL.md");
|
|
16581
|
+
const destSkill = (0, import_node_path19.join)(dest, "SKILL.md");
|
|
16374
16582
|
if ((0, import_node_fs24.existsSync)(destSkill)) {
|
|
16375
16583
|
try {
|
|
16376
16584
|
const srcContent = await (0, import_promises13.readFile)(srcSkill, "utf-8");
|
|
@@ -16408,11 +16616,13 @@ function registerInitCommand(program2) {
|
|
|
16408
16616
|
} catch (err) {
|
|
16409
16617
|
printWarn(` Could not update CLAUDE.md: ${err.message}`);
|
|
16410
16618
|
}
|
|
16411
|
-
const globalVerityDir = (0,
|
|
16619
|
+
const globalVerityDir = (0, import_node_path19.join)(process.env.HOME ?? "", ".verity");
|
|
16412
16620
|
await (0, import_promises13.mkdir)(globalVerityDir, { recursive: true });
|
|
16413
16621
|
console.log("");
|
|
16414
16622
|
try {
|
|
16415
|
-
|
|
16623
|
+
const globals = program2.opts();
|
|
16624
|
+
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
16625
|
+
await runOptionalAuth(urlResult.ok ? urlResult.data : DEFAULT_SERVICE_URL);
|
|
16416
16626
|
} catch (err) {
|
|
16417
16627
|
printWarn(`Authentication step skipped: ${err.message}`);
|
|
16418
16628
|
}
|
|
@@ -16439,7 +16649,7 @@ function registerInitCommand(program2) {
|
|
|
16439
16649
|
|
|
16440
16650
|
// src/commands/uninstall.ts
|
|
16441
16651
|
var import_node_fs25 = require("node:fs");
|
|
16442
|
-
var
|
|
16652
|
+
var import_node_path20 = require("node:path");
|
|
16443
16653
|
var SKILL_NAMES = [
|
|
16444
16654
|
"verity-setup",
|
|
16445
16655
|
"verity-analyze",
|
|
@@ -16458,7 +16668,7 @@ function registerUninstallCommand(program2) {
|
|
|
16458
16668
|
const actions = [];
|
|
16459
16669
|
const skillsRoot = projectPath(".claude/skills");
|
|
16460
16670
|
for (const name of SKILL_NAMES) {
|
|
16461
|
-
const dir = (0,
|
|
16671
|
+
const dir = (0, import_node_path20.join)(skillsRoot, name);
|
|
16462
16672
|
if ((0, import_node_fs25.existsSync)(dir)) {
|
|
16463
16673
|
actions.push({
|
|
16464
16674
|
label: `Remove .claude/skills/${name}/`,
|
|
@@ -16504,7 +16714,7 @@ function registerUninstallCommand(program2) {
|
|
|
16504
16714
|
}
|
|
16505
16715
|
});
|
|
16506
16716
|
const home = process.env.HOME ?? "";
|
|
16507
|
-
const globalVerityDir = (0,
|
|
16717
|
+
const globalVerityDir = (0, import_node_path20.join)(home, ".verity");
|
|
16508
16718
|
if (purgeGlobal && (0, import_node_fs25.existsSync)(globalVerityDir)) {
|
|
16509
16719
|
actions.push({
|
|
16510
16720
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
@@ -16703,7 +16913,7 @@ function registerTaskCommands(program2) {
|
|
|
16703
16913
|
|
|
16704
16914
|
// src/commands/reset.ts
|
|
16705
16915
|
var import_node_fs26 = require("node:fs");
|
|
16706
|
-
var
|
|
16916
|
+
var import_node_path21 = require("node:path");
|
|
16707
16917
|
function registerResetCommand(program2) {
|
|
16708
16918
|
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
16919
|
const globals = program2.opts();
|
|
@@ -16744,7 +16954,7 @@ function registerResetCommand(program2) {
|
|
|
16744
16954
|
for (const entry of (0, import_node_fs26.readdirSync)(cacheDir)) {
|
|
16745
16955
|
if (entry.startsWith("pending-")) {
|
|
16746
16956
|
try {
|
|
16747
|
-
(0, import_node_fs26.unlinkSync)((0,
|
|
16957
|
+
(0, import_node_fs26.unlinkSync)((0, import_node_path21.join)(cacheDir, entry));
|
|
16748
16958
|
purged++;
|
|
16749
16959
|
} catch {
|
|
16750
16960
|
}
|
|
@@ -16771,7 +16981,7 @@ function registerResetCommand(program2) {
|
|
|
16771
16981
|
if ((0, import_node_fs26.existsSync)(logsDir)) {
|
|
16772
16982
|
for (const entry of (0, import_node_fs26.readdirSync)(logsDir)) {
|
|
16773
16983
|
try {
|
|
16774
|
-
(0, import_node_fs26.unlinkSync)((0,
|
|
16984
|
+
(0, import_node_fs26.unlinkSync)((0, import_node_path21.join)(logsDir, entry));
|
|
16775
16985
|
} catch {
|
|
16776
16986
|
}
|
|
16777
16987
|
}
|
|
@@ -16782,24 +16992,6 @@ function registerResetCommand(program2) {
|
|
|
16782
16992
|
});
|
|
16783
16993
|
}
|
|
16784
16994
|
|
|
16785
|
-
// src/lib/run-mode.ts
|
|
16786
|
-
function parseAutonomousEnv(raw) {
|
|
16787
|
-
if (raw === void 0) return void 0;
|
|
16788
|
-
const v = raw.trim().toLowerCase();
|
|
16789
|
-
if (v === "") return void 0;
|
|
16790
|
-
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
16791
|
-
return true;
|
|
16792
|
-
}
|
|
16793
|
-
function resolveRunMode(inputs = {}) {
|
|
16794
|
-
if (inputs.autonomousFlag === true) return "autonomous";
|
|
16795
|
-
if (inputs.autonomousFlag === false) return "interactive";
|
|
16796
|
-
const env = inputs.env ?? process.env;
|
|
16797
|
-
const envDecision = parseAutonomousEnv(env.VERITY_AUTONOMOUS);
|
|
16798
|
-
if (envDecision !== void 0) return envDecision ? "autonomous" : "interactive";
|
|
16799
|
-
const isTTY = inputs.isTTY ?? Boolean(process.stdin?.isTTY);
|
|
16800
|
-
return isTTY ? "interactive" : "autonomous";
|
|
16801
|
-
}
|
|
16802
|
-
|
|
16803
16995
|
// src/commands/reflect.ts
|
|
16804
16996
|
function registerReflectCommand(program2) {
|
|
16805
16997
|
program2.command("reflect").description("Capture learnings \u2014 auto-extract or submit a human reflection").option("--user-input <text>", "The reflection to record (the agent-drafted or user-confirmed text)").option("--kind <kind>", "Node kind (decision, gotcha, pattern, security, quality, intent, domain, integration)", "gotcha").option("--task-id <id>", "Task to reflect on (defaults to current task)").option("--autonomous", "Record the drafted reflection without a confirm step (auto-detected from TTY / VERITY_AUTONOMOUS when omitted)").action(async (opts) => {
|
|
@@ -17161,8 +17353,9 @@ function registerTelemetryCommands(program2) {
|
|
|
17161
17353
|
}
|
|
17162
17354
|
|
|
17163
17355
|
// src/cli.ts
|
|
17164
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.27.
|
|
17356
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.27.2-experimental.5fb996a").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
|
|
17165
17357
|
registerAuthCommands(program);
|
|
17358
|
+
registerLoginCommand(program);
|
|
17166
17359
|
registerHooksCommands(program);
|
|
17167
17360
|
registerIntentCommands(program);
|
|
17168
17361
|
registerStandardCommands(program);
|