@codacy/verity-cli 0.27.1-experimental.f7b7eba → 0.27.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/verity.js +335 -222
  2. 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 = "https://yyfaqvcgslcrzvrbvqik.supabase.co/functions/v1".length > 0 ? "https://yyfaqvcgslcrzvrbvqik.supabase.co/functions/v1" : PROD_SERVICE_URL;
10476
+ var DEFAULT_SERVICE_URL = "".length > 0 ? "" : 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 basename3 = f.split("/").pop() ?? "";
11051
- if (REVIEWABLE_FILENAMES.has(basename3)) return true;
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: user?.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 import_node_path5 = require("node:path");
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 import_node_path4 = require("node:path");
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, import_node_path4.dirname)(file), { recursive: true });
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, import_node_path5.join)(root, CLAUDE_SETTINGS_FILE), "utf-8"));
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, import_node_path5.join)(root, CLAUDE_SETTINGS_FILE), settings);
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 import_node_child_process5 = require("node:child_process");
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, import_node_child_process5.execSync)(
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 import_node_path6 = require("node:path");
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, import_node_path6.join)(TASK_CONTEXT_DIR, file);
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, import_node_path6.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
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 import_node_path7 = require("node:path");
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, import_node_path7.join)(memoryDir(), domain);
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, import_node_path7.join)(domainDir, file), "utf-8");
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 import_node_path8 = require("node:path");
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, import_node_path8.join)(memoryDir2(), domain), { recursive: true });
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, import_node_path8.join)(memoryDir2(), "SCHEMA.md"))) {
12230
- await (0, import_promises9.writeFile)((0, import_node_path8.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
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, import_node_path8.join)(memoryDir2(), "index.md"))) {
12233
- await (0, import_promises9.writeFile)((0, import_node_path8.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
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, import_node_path8.join)(memoryDir2(), "log.md"))) {
12236
- await (0, import_promises9.writeFile)((0, import_node_path8.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
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, import_node_path8.join)(memoryDir2(), domain);
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, import_node_path8.join)(memoryDir2(), filePath);
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, import_node_path8.join)(memoryDir2(), "index.md"), "utf-8");
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, import_node_path8.join)(memoryDir2(), "log.md"), "utf-8");
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, import_node_path8.join)(memoryDir2(), domain);
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, import_node_path8.join)(domainDir, file), "utf-8")));
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, import_node_path8.join)(memoryDir2(), path);
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, import_node_path8.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path8.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
12374
- await (0, import_promises9.writeFile)((0, import_node_path8.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
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, import_node_path8.join)(memoryDir2(), write.path);
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, import_node_path8.dirname)(fullPath), { recursive: true });
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, import_node_path8.join)(memoryDir2(), domain);
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, import_node_path8.join)(domainDir, file), "utf-8");
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, import_node_path8.join)(memoryDir2(), "index.md");
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, import_node_path8.join)(cwd, "CLAUDE.md");
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 import_node_path15 = require("node:path");
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 import_node_path9 = require("node:path");
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, import_node_path9.extname)(filepath).slice(1);
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 import_node_child_process6 = require("node:child_process");
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, import_node_child_process6.execSync)("which codacy-analysis", { stdio: "pipe" });
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, import_node_child_process6.execSync)(
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 import_node_path10 = require("node:path");
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, import_node_path10.join)(dir, entry.name);
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, import_node_path10.join)(process.env.HOME ?? "", ".claude", "plans");
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, import_node_path10.join)(plansDir, f);
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 import_node_path11 = require("node:path");
13747
- var import_node_child_process7 = require("node:child_process");
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, import_node_path11.join)(SNAPSHOT_DIR, file.path);
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, import_node_path11.join)(SNAPSHOT_DIR, file.path);
13870
+ const snapshotPath = (0, import_node_path12.join)(SNAPSHOT_DIR, file.path);
13782
13871
  snapshotPaths.add(snapshotPath);
13783
- (0, import_node_fs12.mkdirSync)((0, import_node_path11.dirname)(snapshotPath), { recursive: true });
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, import_node_path11.join)(SNAPSHOT_DIR, ".diff-old.tmp");
13790
- const tmpNew = (0, import_node_path11.join)(SNAPSHOT_DIR, ".diff-new.tmp");
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, import_node_child_process7.execSync)(
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, import_node_path11.join)(dir, entry.name);
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 import_node_path12 = require("node:path");
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, import_node_path12.join)(projectPath(BASELINE_DIR), key);
13944
+ return (0, import_node_path13.join)(projectPath(BASELINE_DIR), key);
13856
13945
  }
13857
13946
  function manifestPath(dir) {
13858
- return (0, import_node_path12.join)(dir, "manifest.json");
13947
+ return (0, import_node_path13.join)(dir, "manifest.json");
13859
13948
  }
13860
13949
  function mirrorPath(dir, repoRelPath) {
13861
- return (0, import_node_path12.join)(dir, "files", repoRelPath);
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, import_node_path12.join)(dir, "files");
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, import_node_path12.dirname)(dest), { recursive: true });
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, import_node_path12.join)(root, name);
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 import_node_path13 = require("node:path");
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, import_node_path13.join)(dir, entry);
14211
+ const path = (0, import_node_path14.join)(dir, entry);
14123
14212
  try {
14124
14213
  const stat3 = (0, import_node_fs16.statSync)(path);
14125
14214
  if (stat3.mtimeMs < cutoff) {
@@ -14512,7 +14601,7 @@ function capArray(set, max) {
14512
14601
  // src/lib/seed-runner.ts
14513
14602
  var import_promises12 = require("node:fs/promises");
14514
14603
  var import_node_fs18 = require("node:fs");
14515
- var import_node_path14 = require("node:path");
14604
+ var import_node_path15 = require("node:path");
14516
14605
  var import_yaml2 = __toESM(require_dist());
14517
14606
 
14518
14607
  // src/lib/seed.ts
@@ -14794,7 +14883,7 @@ async function runSeed(opts) {
14794
14883
  if (candidates.length === 0) {
14795
14884
  return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
14796
14885
  }
14797
- const overviewPath = (0, import_node_path14.join)(MEMORY_DIR, "domain", "project-overview.md");
14886
+ const overviewPath = (0, import_node_path15.join)(MEMORY_DIR, "domain", "project-overview.md");
14798
14887
  if ((0, import_node_fs18.existsSync)(overviewPath) && !opts.force) {
14799
14888
  return { created: 0, failed: 0, skipped: "already_seeded", candidates };
14800
14889
  }
@@ -14830,9 +14919,9 @@ async function runSeed(opts) {
14830
14919
  }
14831
14920
  const nodeId = res.data.node_id;
14832
14921
  const filePathRel = res.data.file_path;
14833
- const targetPath = (0, import_node_path14.join)(MEMORY_DIR, filePathRel);
14922
+ const targetPath = (0, import_node_path15.join)(MEMORY_DIR, filePathRel);
14834
14923
  try {
14835
- await (0, import_promises12.mkdir)((0, import_node_path14.dirname)(targetPath), { recursive: true });
14924
+ await (0, import_promises12.mkdir)((0, import_node_path15.dirname)(targetPath), { recursive: true });
14836
14925
  await (0, import_promises12.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
14837
14926
  created++;
14838
14927
  opts.onCreated?.(nodeId, filePathRel, c);
@@ -15114,7 +15203,7 @@ async function runAnalyze(opts, globals) {
15114
15203
  let autoSeedNotice = null;
15115
15204
  try {
15116
15205
  await ensureMemoryDir();
15117
- const seedMarker = (0, import_node_path15.join)(VERITY_DIR, ".seeded");
15206
+ const seedMarker = (0, import_node_path16.join)(VERITY_DIR, ".seeded");
15118
15207
  const hasStandard = (0, import_node_fs19.existsSync)(STANDARD_FILE);
15119
15208
  const alreadyTried = (0, import_node_fs19.existsSync)(seedMarker);
15120
15209
  if (hasStandard && !alreadyTried) {
@@ -15348,6 +15437,7 @@ async function runAnalyze(opts, globals) {
15348
15437
  }
15349
15438
  }
15350
15439
  saveSnapshots(codeDelta.files.map((f) => ({ path: f.path, content: f.content })));
15440
+ const loginNudge = response.persisted === false ? " \u26A0\uFE0F Not logged in \u2014 this run was NOT saved and Verity has no memory of your project. Run `verity login` to unlock run history, trends, and cloud memory." : "";
15351
15441
  switch (decision) {
15352
15442
  case "FAIL": {
15353
15443
  writeIteration(iteration + 1, currentCommit, contentHash ?? void 0);
@@ -15420,6 +15510,9 @@ async function runAnalyze(opts, globals) {
15420
15510
  `);
15421
15511
  }
15422
15512
  process.stderr.write(`${BOLD}Fix these issues, then I will re-analyze automatically.${NC}
15513
+ `);
15514
+ if (loginNudge) process.stderr.write(`
15515
+ ${YELLOW}${loginNudge.trim()}${NC}
15423
15516
  `);
15424
15517
  process.exit(2);
15425
15518
  break;
@@ -15432,6 +15525,7 @@ async function runAnalyze(opts, globals) {
15432
15525
  const viewUrl = response.view_url ?? "";
15433
15526
  if (viewUrl) userSummary += ` Report: ${viewUrl}`;
15434
15527
  if (autoSeedNotice) userSummary = `${autoSeedNotice} ${userSummary}`;
15528
+ userSummary += loginNudge;
15435
15529
  printJsonCompact({ gate_decision: "PASS", systemMessage: userSummary });
15436
15530
  process.exit(0);
15437
15531
  break;
@@ -15443,12 +15537,13 @@ async function runAnalyze(opts, globals) {
15443
15537
  const viewUrl = response.view_url ?? "";
15444
15538
  if (viewUrl) userSummary += ` Report: ${viewUrl}`;
15445
15539
  if (autoSeedNotice) userSummary = `${autoSeedNotice} ${userSummary}`;
15540
+ userSummary += loginNudge;
15446
15541
  printJsonCompact({ gate_decision: "WARN", systemMessage: userSummary });
15447
15542
  process.exit(0);
15448
15543
  break;
15449
15544
  }
15450
15545
  default: {
15451
- const msg = autoSeedNotice ? `${autoSeedNotice} Verity: Analysis complete` : "Verity: Analysis complete";
15546
+ const msg = (autoSeedNotice ? `${autoSeedNotice} Verity: Analysis complete` : "Verity: Analysis complete") + loginNudge;
15452
15547
  printJsonCompact({ gate_decision: "PASS", systemMessage: msg });
15453
15548
  process.exit(0);
15454
15549
  }
@@ -15608,9 +15703,9 @@ async function runReview(opts, globals) {
15608
15703
 
15609
15704
  // src/commands/guard.ts
15610
15705
  var import_node_fs22 = require("node:fs");
15611
- var import_node_path16 = require("node:path");
15706
+ var import_node_path17 = require("node:path");
15612
15707
  var GUARD_BLOCK_CAP = 2;
15613
- var GUARD_ITER_FILE = (0, import_node_path16.join)(VERITY_DIR, ".guard-iteration");
15708
+ var GUARD_ITER_FILE = (0, import_node_path17.join)(VERITY_DIR, ".guard-iteration");
15614
15709
  function readPreToolUseStdin() {
15615
15710
  const empty = { command: "", cwd: null, sessionId: null };
15616
15711
  return new Promise((resolve) => {
@@ -15926,21 +16021,21 @@ function writeBlockMessage(moment, response) {
15926
16021
  // src/commands/init.ts
15927
16022
  var import_node_fs24 = require("node:fs");
15928
16023
  var import_promises13 = require("node:fs/promises");
15929
- var import_node_path18 = require("node:path");
15930
- var import_node_child_process9 = require("node:child_process");
16024
+ var import_node_path19 = require("node:path");
16025
+ var import_node_child_process10 = require("node:child_process");
15931
16026
  var readline2 = __toESM(require("node:readline/promises"));
15932
16027
 
15933
16028
  // src/commands/migrate.ts
15934
16029
  var import_node_fs23 = require("node:fs");
15935
- var import_node_path17 = require("node:path");
15936
- var import_node_child_process8 = require("node:child_process");
16030
+ var import_node_path18 = require("node:path");
16031
+ var import_node_child_process9 = require("node:child_process");
15937
16032
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
15938
16033
  function defaultNpmRemover(pkg) {
15939
- (0, import_node_child_process8.execSync)(`npm rm -g ${pkg}`, { stdio: "pipe", timeout: 12e4 });
16034
+ (0, import_node_child_process9.execSync)(`npm rm -g ${pkg}`, { stdio: "pipe", timeout: 12e4 });
15940
16035
  }
15941
16036
  function isGitTracked(cwd, relPath) {
15942
16037
  try {
15943
- (0, import_node_child_process8.execSync)(`git ls-files --error-unmatch ${relPath}`, { cwd, stdio: "pipe" });
16038
+ (0, import_node_child_process9.execSync)(`git ls-files --error-unmatch ${relPath}`, { cwd, stdio: "pipe" });
15944
16039
  return true;
15945
16040
  } catch {
15946
16041
  return false;
@@ -15948,7 +16043,7 @@ function isGitTracked(cwd, relPath) {
15948
16043
  }
15949
16044
  function isGitRepo(cwd) {
15950
16045
  try {
15951
- (0, import_node_child_process8.execSync)("git rev-parse --is-inside-work-tree", { cwd, stdio: "pipe" });
16046
+ (0, import_node_child_process9.execSync)("git rev-parse --is-inside-work-tree", { cwd, stdio: "pipe" });
15952
16047
  return true;
15953
16048
  } catch {
15954
16049
  return false;
@@ -15968,8 +16063,8 @@ async function runMigration(opts = {}) {
15968
16063
  return { actions, migrated: actions.length > 0 };
15969
16064
  }
15970
16065
  function migrateProjectDir(root, actions) {
15971
- const gateDir = (0, import_node_path17.join)(root, ".gate");
15972
- const verityDir = (0, import_node_path17.join)(root, ".verity");
16066
+ const gateDir = (0, import_node_path18.join)(root, ".gate");
16067
+ const verityDir = (0, import_node_path18.join)(root, ".verity");
15973
16068
  if ((0, import_node_fs23.existsSync)(gateDir) && !(0, import_node_fs23.existsSync)(verityDir)) {
15974
16069
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
15975
16070
  }
@@ -15987,7 +16082,7 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
15987
16082
  );
15988
16083
  }
15989
16084
  try {
15990
- (0, import_node_child_process8.execSync)("git mv .gate .verity", { cwd: root, stdio: "pipe" });
16085
+ (0, import_node_child_process9.execSync)("git mv .gate .verity", { cwd: root, stdio: "pipe" });
15991
16086
  actions.push("Moved .gate/ \u2192 .verity/ (git mv, staged)");
15992
16087
  moved = true;
15993
16088
  } catch {
@@ -16023,11 +16118,11 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
16023
16118
  }
16024
16119
  function migrateGlobalCredentials(home, actions) {
16025
16120
  if (!home) return;
16026
- const gateCreds = (0, import_node_path17.join)(home, ".gate", "credentials");
16027
- const verityCreds = (0, import_node_path17.join)(home, ".verity", "credentials");
16121
+ const gateCreds = (0, import_node_path18.join)(home, ".gate", "credentials");
16122
+ const verityCreds = (0, import_node_path18.join)(home, ".verity", "credentials");
16028
16123
  if (!(0, import_node_fs23.existsSync)(gateCreds)) return;
16029
16124
  if (!(0, import_node_fs23.existsSync)(verityCreds)) {
16030
- (0, import_node_fs23.mkdirSync)((0, import_node_path17.join)(home, ".verity"), { recursive: true });
16125
+ (0, import_node_fs23.mkdirSync)((0, import_node_path18.join)(home, ".verity"), { recursive: true });
16031
16126
  moveFile(gateCreds, verityCreds);
16032
16127
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
16033
16128
  return;
@@ -16049,7 +16144,7 @@ async function migrateLegacyHooks(root, actions) {
16049
16144
  }
16050
16145
  }
16051
16146
  async function migrateClaudeMd(root, actions) {
16052
- const claudeMd = (0, import_node_path17.join)(root, "CLAUDE.md");
16147
+ const claudeMd = (0, import_node_path18.join)(root, "CLAUDE.md");
16053
16148
  const hadLegacyBlock = (0, import_node_fs23.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
16054
16149
  if (!hadLegacyBlock) return;
16055
16150
  try {
@@ -16060,13 +16155,13 @@ async function migrateClaudeMd(root, actions) {
16060
16155
  }
16061
16156
  }
16062
16157
  function migrateStandardFile(root, actions) {
16063
- const gateMd = (0, import_node_path17.join)(root, "GATE.md");
16064
- const verityMd = (0, import_node_path17.join)(root, "VERITY.md");
16158
+ const gateMd = (0, import_node_path18.join)(root, "GATE.md");
16159
+ const verityMd = (0, import_node_path18.join)(root, "VERITY.md");
16065
16160
  if (!(0, import_node_fs23.existsSync)(gateMd) || (0, import_node_fs23.existsSync)(verityMd)) return;
16066
16161
  let moved = false;
16067
16162
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
16068
16163
  try {
16069
- (0, import_node_child_process8.execSync)("git mv GATE.md VERITY.md", { cwd: root, stdio: "pipe" });
16164
+ (0, import_node_child_process9.execSync)("git mv GATE.md VERITY.md", { cwd: root, stdio: "pipe" });
16070
16165
  moved = true;
16071
16166
  } catch {
16072
16167
  }
@@ -16122,7 +16217,7 @@ function readFileSyncSafe(path) {
16122
16217
  }
16123
16218
  function hasStagedChanges(root) {
16124
16219
  try {
16125
- (0, import_node_child_process8.execSync)("git diff --cached --quiet", { cwd: root, stdio: "pipe" });
16220
+ (0, import_node_child_process9.execSync)("git diff --cached --quiet", { cwd: root, stdio: "pipe" });
16126
16221
  return false;
16127
16222
  } catch {
16128
16223
  return true;
@@ -16149,15 +16244,15 @@ function moveFile(from, to) {
16149
16244
  function carryLegacyContents(gateDir, verityDir) {
16150
16245
  let copied = 0;
16151
16246
  const walk = (relDir) => {
16152
- const srcDir = (0, import_node_path17.join)(gateDir, relDir);
16247
+ const srcDir = (0, import_node_path18.join)(gateDir, relDir);
16153
16248
  for (const entry of (0, import_node_fs23.readdirSync)(srcDir)) {
16154
- const rel = relDir ? (0, import_node_path17.join)(relDir, entry) : entry;
16155
- const src = (0, import_node_path17.join)(gateDir, rel);
16156
- const dest = (0, import_node_path17.join)(verityDir, rel);
16249
+ const rel = relDir ? (0, import_node_path18.join)(relDir, entry) : entry;
16250
+ const src = (0, import_node_path18.join)(gateDir, rel);
16251
+ const dest = (0, import_node_path18.join)(verityDir, rel);
16157
16252
  if ((0, import_node_fs23.statSync)(src).isDirectory()) {
16158
16253
  walk(rel);
16159
16254
  } else if (!(0, import_node_fs23.existsSync)(dest)) {
16160
- (0, import_node_fs23.mkdirSync)((0, import_node_path17.dirname)(dest), { recursive: true });
16255
+ (0, import_node_fs23.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
16161
16256
  (0, import_node_fs23.cpSync)(src, dest);
16162
16257
  copied++;
16163
16258
  }
@@ -16167,22 +16262,22 @@ function carryLegacyContents(gateDir, verityDir) {
16167
16262
  return copied;
16168
16263
  }
16169
16264
  async function needsMigration(root = repoRoot()) {
16170
- const gateDir = (0, import_node_path17.join)(root, ".gate");
16171
- const verityDir = (0, import_node_path17.join)(root, ".verity");
16265
+ const gateDir = (0, import_node_path18.join)(root, ".gate");
16266
+ const verityDir = (0, import_node_path18.join)(root, ".verity");
16172
16267
  if ((0, import_node_fs23.existsSync)(gateDir) && !(0, import_node_fs23.existsSync)(verityDir)) return true;
16173
16268
  if ((0, import_node_fs23.existsSync)(gateDir) && (0, import_node_fs23.existsSync)(verityDir)) {
16174
- if ((0, import_node_fs23.existsSync)((0, import_node_path17.join)(gateDir, "credentials")) && !(0, import_node_fs23.existsSync)((0, import_node_path17.join)(verityDir, "credentials"))) {
16269
+ if ((0, import_node_fs23.existsSync)((0, import_node_path18.join)(gateDir, "credentials")) && !(0, import_node_fs23.existsSync)((0, import_node_path18.join)(verityDir, "credentials"))) {
16175
16270
  return true;
16176
16271
  }
16177
- if ((0, import_node_fs23.existsSync)((0, import_node_path17.join)(gateDir, "memory")) && !(0, import_node_fs23.existsSync)((0, import_node_path17.join)(verityDir, "memory"))) {
16272
+ if ((0, import_node_fs23.existsSync)((0, import_node_path18.join)(gateDir, "memory")) && !(0, import_node_fs23.existsSync)((0, import_node_path18.join)(verityDir, "memory"))) {
16178
16273
  return true;
16179
16274
  }
16180
16275
  }
16181
- const claudeMd = (0, import_node_path17.join)(root, "CLAUDE.md");
16276
+ const claudeMd = (0, import_node_path18.join)(root, "CLAUDE.md");
16182
16277
  if ((0, import_node_fs23.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
16183
16278
  return true;
16184
16279
  }
16185
- if ((0, import_node_fs23.existsSync)((0, import_node_path17.join)(root, "GATE.md")) && !(0, import_node_fs23.existsSync)((0, import_node_path17.join)(root, "VERITY.md"))) {
16280
+ if ((0, import_node_fs23.existsSync)((0, import_node_path18.join)(root, "GATE.md")) && !(0, import_node_fs23.existsSync)((0, import_node_path18.join)(root, "VERITY.md"))) {
16186
16281
  return true;
16187
16282
  }
16188
16283
  if (await hasLegacyHooksAt(root)) return true;
@@ -16218,15 +16313,30 @@ async function promptYes(question) {
16218
16313
  rl.close();
16219
16314
  }
16220
16315
  }
16221
- async function runOptionalAuth() {
16316
+ async function runOptionalAuth(serviceUrl) {
16222
16317
  const existing = await resolveToken();
16223
16318
  if (existing.ok) {
16224
- printInfo("Already authenticated \u2014 results will upload to the Verity service. \u2713");
16225
- return;
16319
+ const who = await whoami(existing.data.token, serviceUrl);
16320
+ if (who.ok && who.data.logged_in) {
16321
+ printInfo(`Logged in as ${who.data.email ?? `user #${who.data.user_id}`} \u2713 \u2014 runs & memory sync to Verity.`);
16322
+ return;
16323
+ }
16324
+ if (!who.ok) {
16325
+ if (existing.data.userId != null) {
16326
+ printInfo(`Logged in as ${existing.data.email ?? `user #${existing.data.userId}`} (cached \u2014 could not reach the Verity service). \u2713`);
16327
+ } else {
16328
+ printInfo("Could not confirm your login state with the service; continuing with your existing token.");
16329
+ }
16330
+ return;
16331
+ }
16332
+ console.log("");
16333
+ printWarn("You are NOT logged in \u2014 this project has only an anonymous token.");
16334
+ printInfo(" The gate still runs, but no runs are saved and Verity keeps no memory of this project.");
16335
+ printInfo(" Log in below to unlock run history, trends, and cloud memory (strongly recommended).");
16226
16336
  }
16227
16337
  let remote = "";
16228
16338
  try {
16229
- remote = (0, import_node_child_process9.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
16339
+ remote = (0, import_node_child_process10.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
16230
16340
  } catch {
16231
16341
  }
16232
16342
  const localOnlyNote = () => {
@@ -16257,12 +16367,12 @@ async function runOptionalAuth() {
16257
16367
  localOnlyNote();
16258
16368
  return;
16259
16369
  }
16260
- const projectName = parseRemote(remote)?.repo ?? (0, import_node_path18.basename)(process.cwd());
16370
+ const projectName = parseRemote(remote)?.repo ?? (0, import_node_path19.basename)(process.cwd());
16261
16371
  printInfo("Authenticating with GitHub\u2026");
16262
- const result = await registerProject({ projectName, remote, serviceUrl: DEFAULT_SERVICE_URL });
16372
+ const result = await registerProject({ projectName, remote, serviceUrl });
16263
16373
  if (result.ok) {
16264
- printInfo(`Project registered: ${result.data.projectId} \u2713`);
16265
- if (result.data.email) printInfo(` Authenticated as: ${result.data.email}`);
16374
+ const who = result.data.email ?? (result.data.userId != null ? `user #${result.data.userId}` : null);
16375
+ printInfo(`Logged in${who ? ` as ${who}` : ""} \u2713 \u2014 runs, history, and cloud memory now sync to Verity.`);
16266
16376
  } else {
16267
16377
  printWarn(`Authentication did not complete: ${result.error}`);
16268
16378
  localOnlyNote();
@@ -16270,15 +16380,15 @@ async function runOptionalAuth() {
16270
16380
  }
16271
16381
  function resolveDataDir() {
16272
16382
  const candidates = [
16273
- (0, import_node_path18.join)(__dirname, "..", "data"),
16383
+ (0, import_node_path19.join)(__dirname, "..", "data"),
16274
16384
  // installed: node_modules/@codacy/verity-cli/data
16275
- (0, import_node_path18.join)(__dirname, "..", "..", "data"),
16385
+ (0, import_node_path19.join)(__dirname, "..", "..", "data"),
16276
16386
  // edge case: nested resolution
16277
- (0, import_node_path18.join)(process.cwd(), "cli", "data")
16387
+ (0, import_node_path19.join)(process.cwd(), "cli", "data")
16278
16388
  // local dev: running from repo root
16279
16389
  ];
16280
16390
  for (const candidate of candidates) {
16281
- if ((0, import_node_fs24.existsSync)((0, import_node_path18.join)(candidate, "skills"))) {
16391
+ if ((0, import_node_fs24.existsSync)((0, import_node_path19.join)(candidate, "skills"))) {
16282
16392
  return candidate;
16283
16393
  }
16284
16394
  }
@@ -16322,30 +16432,30 @@ function registerInitCommand(program2) {
16322
16432
  }
16323
16433
  printInfo(` Node.js ${nodeVersion} \u2713`);
16324
16434
  try {
16325
- const gitVersion = (0, import_node_child_process9.execSync)("git --version", { encoding: "utf-8" }).trim();
16435
+ const gitVersion = (0, import_node_child_process10.execSync)("git --version", { encoding: "utf-8" }).trim();
16326
16436
  printInfo(` ${gitVersion} \u2713`);
16327
16437
  } catch {
16328
16438
  printError("git is required but not installed. Install from https://git-scm.com");
16329
16439
  process.exit(1);
16330
16440
  }
16331
16441
  try {
16332
- (0, import_node_child_process9.execSync)("which claude", { encoding: "utf-8" });
16442
+ (0, import_node_child_process10.execSync)("which claude", { encoding: "utf-8" });
16333
16443
  printInfo(" Claude Code \u2713");
16334
16444
  } catch {
16335
16445
  printWarn(" Claude Code not found \u2014 hooks will be configured but need Claude Code to run.");
16336
16446
  }
16337
16447
  try {
16338
- (0, import_node_child_process9.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
16448
+ (0, import_node_child_process10.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
16339
16449
  printInfo(" @codacy/analysis-cli \u2713");
16340
16450
  } catch {
16341
16451
  printInfo(" Installing @codacy/analysis-cli...");
16342
16452
  try {
16343
- (0, import_node_child_process9.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
16453
+ (0, import_node_child_process10.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
16344
16454
  printInfo(" @codacy/analysis-cli installed \u2713");
16345
16455
  } catch {
16346
16456
  try {
16347
16457
  printWarn(" Retrying with sudo...");
16348
- (0, import_node_child_process9.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
16458
+ (0, import_node_child_process10.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
16349
16459
  printInfo(" @codacy/analysis-cli installed \u2713");
16350
16460
  } catch {
16351
16461
  printWarn(" Could not install @codacy/analysis-cli automatically.");
@@ -16357,20 +16467,20 @@ function registerInitCommand(program2) {
16357
16467
  console.log("");
16358
16468
  printInfo("Installing skills...");
16359
16469
  const dataDir = resolveDataDir();
16360
- const skillsSource = (0, import_node_path18.join)(dataDir, "skills");
16470
+ const skillsSource = (0, import_node_path19.join)(dataDir, "skills");
16361
16471
  const skillsDest = ".claude/skills";
16362
16472
  const skills = ["verity-setup", "verity-analyze", "verity-status", "verity-feedback", "verity-learn", "verity-memory", "verity-insights", "verity-reflect"];
16363
16473
  let skillsInstalled = 0;
16364
16474
  for (const skill of skills) {
16365
- const src = (0, import_node_path18.join)(skillsSource, skill);
16366
- const dest = (0, import_node_path18.join)(skillsDest, skill);
16475
+ const src = (0, import_node_path19.join)(skillsSource, skill);
16476
+ const dest = (0, import_node_path19.join)(skillsDest, skill);
16367
16477
  if (!(0, import_node_fs24.existsSync)(src)) {
16368
16478
  printWarn(` Skill data not found: ${skill}`);
16369
16479
  continue;
16370
16480
  }
16371
16481
  if ((0, import_node_fs24.existsSync)(dest) && !force) {
16372
- const srcSkill = (0, import_node_path18.join)(src, "SKILL.md");
16373
- const destSkill = (0, import_node_path18.join)(dest, "SKILL.md");
16482
+ const srcSkill = (0, import_node_path19.join)(src, "SKILL.md");
16483
+ const destSkill = (0, import_node_path19.join)(dest, "SKILL.md");
16374
16484
  if ((0, import_node_fs24.existsSync)(destSkill)) {
16375
16485
  try {
16376
16486
  const srcContent = await (0, import_promises13.readFile)(srcSkill, "utf-8");
@@ -16408,11 +16518,13 @@ function registerInitCommand(program2) {
16408
16518
  } catch (err) {
16409
16519
  printWarn(` Could not update CLAUDE.md: ${err.message}`);
16410
16520
  }
16411
- const globalVerityDir = (0, import_node_path18.join)(process.env.HOME ?? "", ".verity");
16521
+ const globalVerityDir = (0, import_node_path19.join)(process.env.HOME ?? "", ".verity");
16412
16522
  await (0, import_promises13.mkdir)(globalVerityDir, { recursive: true });
16413
16523
  console.log("");
16414
16524
  try {
16415
- await runOptionalAuth();
16525
+ const globals = program2.opts();
16526
+ const urlResult = await resolveServiceUrl(globals.serviceUrl);
16527
+ await runOptionalAuth(urlResult.ok ? urlResult.data : DEFAULT_SERVICE_URL);
16416
16528
  } catch (err) {
16417
16529
  printWarn(`Authentication step skipped: ${err.message}`);
16418
16530
  }
@@ -16439,7 +16551,7 @@ function registerInitCommand(program2) {
16439
16551
 
16440
16552
  // src/commands/uninstall.ts
16441
16553
  var import_node_fs25 = require("node:fs");
16442
- var import_node_path19 = require("node:path");
16554
+ var import_node_path20 = require("node:path");
16443
16555
  var SKILL_NAMES = [
16444
16556
  "verity-setup",
16445
16557
  "verity-analyze",
@@ -16458,7 +16570,7 @@ function registerUninstallCommand(program2) {
16458
16570
  const actions = [];
16459
16571
  const skillsRoot = projectPath(".claude/skills");
16460
16572
  for (const name of SKILL_NAMES) {
16461
- const dir = (0, import_node_path19.join)(skillsRoot, name);
16573
+ const dir = (0, import_node_path20.join)(skillsRoot, name);
16462
16574
  if ((0, import_node_fs25.existsSync)(dir)) {
16463
16575
  actions.push({
16464
16576
  label: `Remove .claude/skills/${name}/`,
@@ -16504,7 +16616,7 @@ function registerUninstallCommand(program2) {
16504
16616
  }
16505
16617
  });
16506
16618
  const home = process.env.HOME ?? "";
16507
- const globalVerityDir = (0, import_node_path19.join)(home, ".verity");
16619
+ const globalVerityDir = (0, import_node_path20.join)(home, ".verity");
16508
16620
  if (purgeGlobal && (0, import_node_fs25.existsSync)(globalVerityDir)) {
16509
16621
  actions.push({
16510
16622
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
@@ -16703,7 +16815,7 @@ function registerTaskCommands(program2) {
16703
16815
 
16704
16816
  // src/commands/reset.ts
16705
16817
  var import_node_fs26 = require("node:fs");
16706
- var import_node_path20 = require("node:path");
16818
+ var import_node_path21 = require("node:path");
16707
16819
  function registerResetCommand(program2) {
16708
16820
  program2.command("reset").description("Close the current task and clear transient state").option("--keep-task", "Only purge caches; leave the current task open").option("--all", "Also purge diagnostic logs (.verity/.logs/)").action(async (opts) => {
16709
16821
  const globals = program2.opts();
@@ -16744,7 +16856,7 @@ function registerResetCommand(program2) {
16744
16856
  for (const entry of (0, import_node_fs26.readdirSync)(cacheDir)) {
16745
16857
  if (entry.startsWith("pending-")) {
16746
16858
  try {
16747
- (0, import_node_fs26.unlinkSync)((0, import_node_path20.join)(cacheDir, entry));
16859
+ (0, import_node_fs26.unlinkSync)((0, import_node_path21.join)(cacheDir, entry));
16748
16860
  purged++;
16749
16861
  } catch {
16750
16862
  }
@@ -16771,7 +16883,7 @@ function registerResetCommand(program2) {
16771
16883
  if ((0, import_node_fs26.existsSync)(logsDir)) {
16772
16884
  for (const entry of (0, import_node_fs26.readdirSync)(logsDir)) {
16773
16885
  try {
16774
- (0, import_node_fs26.unlinkSync)((0, import_node_path20.join)(logsDir, entry));
16886
+ (0, import_node_fs26.unlinkSync)((0, import_node_path21.join)(logsDir, entry));
16775
16887
  } catch {
16776
16888
  }
16777
16889
  }
@@ -17161,8 +17273,9 @@ function registerTelemetryCommands(program2) {
17161
17273
  }
17162
17274
 
17163
17275
  // src/cli.ts
17164
- program.name("verity").description("CLI for Verity quality gate service").version("0.27.1-experimental.f7b7eba").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
17276
+ program.name("verity").description("CLI for Verity quality gate service").version("0.27.2").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
17165
17277
  registerAuthCommands(program);
17278
+ registerLoginCommand(program);
17166
17279
  registerHooksCommands(program);
17167
17280
  registerIntentCommands(program);
17168
17281
  registerStandardCommands(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/verity-cli",
3
- "version": "0.27.1-experimental.f7b7eba",
3
+ "version": "0.27.2",
4
4
  "description": "CLI for Verity quality gate service",
5
5
  "homepage": "https://verity.md",
6
6
  "repository": {