@codacy/verity-cli 0.27.2 → 0.28.1
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 +313 -123
- package/package.json +1 -5
package/bin/verity.js
CHANGED
|
@@ -10328,7 +10328,7 @@ var {
|
|
|
10328
10328
|
var import_node_child_process4 = require("node:child_process");
|
|
10329
10329
|
|
|
10330
10330
|
// src/lib/auth.ts
|
|
10331
|
-
var
|
|
10331
|
+
var import_promises2 = require("node:fs/promises");
|
|
10332
10332
|
var import_node_child_process2 = require("node:child_process");
|
|
10333
10333
|
|
|
10334
10334
|
// src/constants.ts
|
|
@@ -10551,6 +10551,13 @@ function rotateIfNeeded(file) {
|
|
|
10551
10551
|
}
|
|
10552
10552
|
|
|
10553
10553
|
// src/lib/api-client.ts
|
|
10554
|
+
function describeFetchError(err, url) {
|
|
10555
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
10556
|
+
const cause = err?.cause;
|
|
10557
|
+
const causeBits = [cause?.code, cause?.hostname].filter(Boolean).join(" ");
|
|
10558
|
+
const detail = causeBits || (cause?.message && cause.message !== message ? cause.message : "");
|
|
10559
|
+
return `${message}${detail ? ` (${detail})` : ""} \u2014 could not reach ${url}`;
|
|
10560
|
+
}
|
|
10554
10561
|
async function apiRequest(options) {
|
|
10555
10562
|
const {
|
|
10556
10563
|
method,
|
|
@@ -10606,7 +10613,7 @@ async function apiRequest(options) {
|
|
|
10606
10613
|
const duration2 = Date.now() - startedAt;
|
|
10607
10614
|
const isTimeout = err instanceof DOMException && err.name === "TimeoutError";
|
|
10608
10615
|
const category = isTimeout ? "timeout" : "network";
|
|
10609
|
-
const error = isTimeout ? `Request timed out after ${timeout}ms` : `Network error: ${err
|
|
10616
|
+
const error = isTimeout ? `Request timed out after ${timeout}ms (${url})` : `Network error: ${describeFetchError(err, url)}`;
|
|
10610
10617
|
logHttpCall({ ...logBase, duration_ms: duration2, http_status: null, category, error });
|
|
10611
10618
|
return { ok: false, error, category, http_status: null };
|
|
10612
10619
|
}
|
|
@@ -10665,6 +10672,60 @@ function analyzeRequest(options) {
|
|
|
10665
10672
|
});
|
|
10666
10673
|
}
|
|
10667
10674
|
|
|
10675
|
+
// src/lib/service-url.ts
|
|
10676
|
+
var import_promises = require("node:fs/promises");
|
|
10677
|
+
async function serviceUrlFromCredentials() {
|
|
10678
|
+
try {
|
|
10679
|
+
const creds = await (0, import_promises.readFile)(projectPath(CREDENTIALS_FILE), "utf-8");
|
|
10680
|
+
const match = creds.match(/service_url:\s*(https?:\/\/[^\s]+)/);
|
|
10681
|
+
return match ? match[1] : null;
|
|
10682
|
+
} catch {
|
|
10683
|
+
return null;
|
|
10684
|
+
}
|
|
10685
|
+
}
|
|
10686
|
+
async function serviceUrlFromVerityMd() {
|
|
10687
|
+
try {
|
|
10688
|
+
const content = await (0, import_promises.readFile)(projectPath(VERITY_MD_FILE), "utf-8");
|
|
10689
|
+
const boldLine = content.split("\n").find((l) => /\*\*url\*\*/i.test(l));
|
|
10690
|
+
if (boldLine) {
|
|
10691
|
+
const urlMatch = boldLine.match(/https:\/\/[^\s]+/);
|
|
10692
|
+
if (urlMatch) return urlMatch[0];
|
|
10693
|
+
}
|
|
10694
|
+
const plainLine = content.split("\n").find((l) => /(?:url|service)\s*:/i.test(l));
|
|
10695
|
+
if (plainLine) {
|
|
10696
|
+
const urlMatch = plainLine.match(/https:\/\/[^\s]+/);
|
|
10697
|
+
if (urlMatch) return urlMatch[0];
|
|
10698
|
+
}
|
|
10699
|
+
} catch {
|
|
10700
|
+
}
|
|
10701
|
+
return null;
|
|
10702
|
+
}
|
|
10703
|
+
async function resolveServiceUrlDetailed(flagUrl) {
|
|
10704
|
+
if (flagUrl) {
|
|
10705
|
+
return { ok: true, data: { url: flagUrl, source: "flag" } };
|
|
10706
|
+
}
|
|
10707
|
+
const envUrl = process.env.VERITY_SERVICE_URL;
|
|
10708
|
+
if (envUrl) {
|
|
10709
|
+
return { ok: true, data: { url: envUrl, source: "env" } };
|
|
10710
|
+
}
|
|
10711
|
+
const credsUrl = await serviceUrlFromCredentials();
|
|
10712
|
+
if (credsUrl) {
|
|
10713
|
+
return { ok: true, data: { url: credsUrl, source: "credentials" } };
|
|
10714
|
+
}
|
|
10715
|
+
const mdUrl = await serviceUrlFromVerityMd();
|
|
10716
|
+
if (mdUrl) {
|
|
10717
|
+
return { ok: true, data: { url: mdUrl, source: "verity_md" } };
|
|
10718
|
+
}
|
|
10719
|
+
return { ok: false, error: "No Verity service URL found. Run /verity-setup to configure." };
|
|
10720
|
+
}
|
|
10721
|
+
async function resolveServiceUrl(flagUrl) {
|
|
10722
|
+
const result = await resolveServiceUrlDetailed(flagUrl);
|
|
10723
|
+
return result.ok ? { ok: true, data: result.data.url } : result;
|
|
10724
|
+
}
|
|
10725
|
+
function isHealCandidate(resolved) {
|
|
10726
|
+
return (resolved.source === "credentials" || resolved.source === "verity_md") && resolved.url !== DEFAULT_SERVICE_URL;
|
|
10727
|
+
}
|
|
10728
|
+
|
|
10668
10729
|
// src/lib/auth.ts
|
|
10669
10730
|
function parseIdentity(content) {
|
|
10670
10731
|
const idMatch = content.match(/^user_id:\s*(\d+)/m);
|
|
@@ -10683,7 +10744,7 @@ async function resolveToken(flagToken) {
|
|
|
10683
10744
|
return { ok: true, data: { token: envToken, source: "env" } };
|
|
10684
10745
|
}
|
|
10685
10746
|
try {
|
|
10686
|
-
const content = await (0,
|
|
10747
|
+
const content = await (0, import_promises2.readFile)(projectPath(CREDENTIALS_FILE), "utf-8");
|
|
10687
10748
|
const match = content.match(/token:\s*((?:gate_|verity_)[a-f0-9]+)/);
|
|
10688
10749
|
if (match) {
|
|
10689
10750
|
return { ok: true, data: { token: match[1], source: "local", ...parseIdentity(content) } };
|
|
@@ -10692,7 +10753,7 @@ async function resolveToken(flagToken) {
|
|
|
10692
10753
|
}
|
|
10693
10754
|
const globalCredentials = `${process.env.HOME}/.verity/credentials`;
|
|
10694
10755
|
try {
|
|
10695
|
-
const content = await (0,
|
|
10756
|
+
const content = await (0, import_promises2.readFile)(globalCredentials, "utf-8");
|
|
10696
10757
|
let remote = "";
|
|
10697
10758
|
try {
|
|
10698
10759
|
remote = (0, import_node_child_process2.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
|
|
@@ -10721,50 +10782,44 @@ async function whoami(token, serviceUrl, verbose) {
|
|
|
10721
10782
|
path: "/auth/whoami",
|
|
10722
10783
|
serviceUrl,
|
|
10723
10784
|
token,
|
|
10724
|
-
verbose
|
|
10785
|
+
verbose,
|
|
10786
|
+
cmd: "whoami"
|
|
10725
10787
|
});
|
|
10726
10788
|
}
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
10789
|
+
async function probeService(serviceUrl, verbose) {
|
|
10790
|
+
const res = await apiRequest({
|
|
10791
|
+
method: "GET",
|
|
10792
|
+
path: "/auth/whoami",
|
|
10793
|
+
serviceUrl,
|
|
10794
|
+
verbose,
|
|
10795
|
+
timeout: 5e3,
|
|
10796
|
+
cmd: "probe"
|
|
10797
|
+
});
|
|
10798
|
+
if (res.ok || res.http_status != null) return { reachable: true };
|
|
10799
|
+
return { reachable: false, dnsDead: /\bENOTFOUND\b/.test(res.error), error: res.error };
|
|
10800
|
+
}
|
|
10801
|
+
async function maybeHealServiceUrl(resolution, verbose) {
|
|
10802
|
+
if (!isHealCandidate(resolution)) {
|
|
10803
|
+
return { serviceUrl: resolution.url, healed: false };
|
|
10737
10804
|
}
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
if (match) {
|
|
10742
|
-
return { ok: true, data: match[1] };
|
|
10743
|
-
}
|
|
10744
|
-
} catch {
|
|
10805
|
+
const probe = await probeService(resolution.url, verbose);
|
|
10806
|
+
if (probe.reachable) {
|
|
10807
|
+
return { serviceUrl: resolution.url, healed: false };
|
|
10745
10808
|
}
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
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
|
-
}
|
|
10809
|
+
const from = resolution.source === "credentials" ? ".verity/credentials" : "VERITY.md";
|
|
10810
|
+
printWarn(`Your configured Verity service URL is unreachable: ${resolution.url}`);
|
|
10811
|
+
printInfo(` (${probe.error})`);
|
|
10812
|
+
if (probe.dnsDead && (await probeService(DEFAULT_SERVICE_URL, verbose)).reachable) {
|
|
10813
|
+
printInfo(` The hostname no longer exists \u2014 the URL in ${from} is stale (e.g. a retired preview backend).`);
|
|
10814
|
+
printInfo(` Falling back to the default Verity service: ${DEFAULT_SERVICE_URL}`);
|
|
10815
|
+
if (resolution.source === "verity_md") {
|
|
10816
|
+
printWarn(` Note: VERITY.md still contains the stale URL \u2014 update it to ${DEFAULT_SERVICE_URL} and commit.`);
|
|
10764
10817
|
}
|
|
10765
|
-
|
|
10818
|
+
return { serviceUrl: DEFAULT_SERVICE_URL, healed: true };
|
|
10766
10819
|
}
|
|
10767
|
-
|
|
10820
|
+
printInfo(" Continuing against the configured URL. If it is stale, log in against the default with:");
|
|
10821
|
+
printInfo(` VERITY_SERVICE_URL=${DEFAULT_SERVICE_URL} verity login`);
|
|
10822
|
+
return { serviceUrl: resolution.url, healed: false };
|
|
10768
10823
|
}
|
|
10769
10824
|
|
|
10770
10825
|
// src/lib/register.ts
|
|
@@ -11185,7 +11240,8 @@ async function registerProject(opts) {
|
|
|
11185
11240
|
serviceUrl: opts.serviceUrl,
|
|
11186
11241
|
body: { project_name: opts.projectName, git_remote_url: opts.remote },
|
|
11187
11242
|
extraHeaders: { "X-Provider-Token": providerToken },
|
|
11188
|
-
verbose: opts.verbose
|
|
11243
|
+
verbose: opts.verbose,
|
|
11244
|
+
cmd: "register"
|
|
11189
11245
|
});
|
|
11190
11246
|
if (!result.ok) {
|
|
11191
11247
|
return { ok: false, error: result.error };
|
|
@@ -11321,14 +11377,18 @@ var import_node_path4 = require("node:path");
|
|
|
11321
11377
|
function registerLoginCommand(program2) {
|
|
11322
11378
|
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
11379
|
const globals = program2.opts();
|
|
11324
|
-
const urlResult = await
|
|
11380
|
+
const urlResult = await resolveServiceUrlDetailed(globals.serviceUrl);
|
|
11325
11381
|
if (!urlResult.ok) {
|
|
11326
11382
|
printError(urlResult.error);
|
|
11327
11383
|
process.exit(1);
|
|
11328
11384
|
}
|
|
11329
|
-
const
|
|
11385
|
+
const heal = await maybeHealServiceUrl(urlResult.data, globals.verbose);
|
|
11386
|
+
const serviceUrl = heal.serviceUrl;
|
|
11387
|
+
if (heal.healed) {
|
|
11388
|
+
printInfo(" Completing login re-registers this project and updates .verity/credentials.");
|
|
11389
|
+
}
|
|
11330
11390
|
const existing = await resolveToken(globals.token);
|
|
11331
|
-
if (existing.ok && !opts.force) {
|
|
11391
|
+
if (existing.ok && !opts.force && !heal.healed) {
|
|
11332
11392
|
if (existing.data.userId != null) {
|
|
11333
11393
|
printInfo(`Already logged in as ${existing.data.email ?? `user #${existing.data.userId}`}. \u2713`);
|
|
11334
11394
|
printInfo(" Re-authenticate with: verity login --force");
|
|
@@ -11827,7 +11887,7 @@ function registerHooksCommands(program2) {
|
|
|
11827
11887
|
}
|
|
11828
11888
|
|
|
11829
11889
|
// src/commands/intent.ts
|
|
11830
|
-
var
|
|
11890
|
+
var import_node_crypto4 = require("node:crypto");
|
|
11831
11891
|
|
|
11832
11892
|
// src/lib/conversation-buffer.ts
|
|
11833
11893
|
var import_promises6 = require("node:fs/promises");
|
|
@@ -11946,6 +12006,19 @@ function getRecentCommitMessages() {
|
|
|
11946
12006
|
}
|
|
11947
12007
|
}
|
|
11948
12008
|
|
|
12009
|
+
// src/lib/context-identity.ts
|
|
12010
|
+
var import_node_crypto2 = require("node:crypto");
|
|
12011
|
+
function contextIdentity(token, sessionId) {
|
|
12012
|
+
const t = (token ?? "").trim();
|
|
12013
|
+
const s = (sessionId ?? "").trim();
|
|
12014
|
+
const userKey = t.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
|
|
12015
|
+
const sessionKey2 = s.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
|
|
12016
|
+
return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
|
|
12017
|
+
}
|
|
12018
|
+
function sessionScopeKey(token, sessionId) {
|
|
12019
|
+
return contextIdentity(token, sessionId).bucket;
|
|
12020
|
+
}
|
|
12021
|
+
|
|
11949
12022
|
// src/lib/task-context-buffer.ts
|
|
11950
12023
|
var import_promises7 = require("node:fs/promises");
|
|
11951
12024
|
var import_node_fs4 = require("node:fs");
|
|
@@ -12233,7 +12306,7 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
12233
12306
|
var import_promises9 = require("node:fs/promises");
|
|
12234
12307
|
var import_node_fs6 = require("node:fs");
|
|
12235
12308
|
var import_node_path9 = require("node:path");
|
|
12236
|
-
var
|
|
12309
|
+
var import_node_crypto3 = require("node:crypto");
|
|
12237
12310
|
|
|
12238
12311
|
// src/lib/glob-match.ts
|
|
12239
12312
|
function globToRegex(glob) {
|
|
@@ -12331,7 +12404,7 @@ async function buildManifest() {
|
|
|
12331
12404
|
const fullPath = (0, import_node_path9.join)(memoryDir2(), filePath);
|
|
12332
12405
|
try {
|
|
12333
12406
|
const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
12334
|
-
const hash = (0,
|
|
12407
|
+
const hash = (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
12335
12408
|
nodes.push({ path: filePath, content_hash: `sha256:${hash}` });
|
|
12336
12409
|
} catch {
|
|
12337
12410
|
}
|
|
@@ -12342,7 +12415,7 @@ async function buildManifest() {
|
|
|
12342
12415
|
let indexHash = null;
|
|
12343
12416
|
try {
|
|
12344
12417
|
const indexContent = await (0, import_promises9.readFile)((0, import_node_path9.join)(memoryDir2(), "index.md"), "utf-8");
|
|
12345
|
-
indexHash = `sha256:${(0,
|
|
12418
|
+
indexHash = `sha256:${(0, import_node_crypto3.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
|
|
12346
12419
|
} catch {
|
|
12347
12420
|
}
|
|
12348
12421
|
let logLength = 0;
|
|
@@ -12354,7 +12427,7 @@ async function buildManifest() {
|
|
|
12354
12427
|
return { schema_version: 1, nodes, index_hash: indexHash, log_length: logLength };
|
|
12355
12428
|
}
|
|
12356
12429
|
function hashContent(content) {
|
|
12357
|
-
return `sha256:${(0,
|
|
12430
|
+
return `sha256:${(0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16)}`;
|
|
12358
12431
|
}
|
|
12359
12432
|
async function readOnDiskNodes() {
|
|
12360
12433
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -12799,7 +12872,10 @@ function registerIntentCommands(program2) {
|
|
|
12799
12872
|
if (!prompt) {
|
|
12800
12873
|
process.exit(0);
|
|
12801
12874
|
}
|
|
12802
|
-
await
|
|
12875
|
+
const authForScope = await resolveToken(program2.opts().token);
|
|
12876
|
+
const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
|
|
12877
|
+
const scopeSession = event.session_id || process.env.CLAUDE_SESSION_ID || "";
|
|
12878
|
+
await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
|
|
12803
12879
|
try {
|
|
12804
12880
|
await ensureMemoryDir();
|
|
12805
12881
|
const injection = await retrieveForInjection(prompt);
|
|
@@ -12841,7 +12917,7 @@ async function fireClassify(prompt, sessionId) {
|
|
|
12841
12917
|
logEvent("classify_skipped", { reason: "no_service_url", detail: urlResult.error });
|
|
12842
12918
|
return;
|
|
12843
12919
|
}
|
|
12844
|
-
const promptHash = (0,
|
|
12920
|
+
const promptHash = (0, import_node_crypto4.createHash)("sha256").update(prompt).digest("hex");
|
|
12845
12921
|
const result = await apiRequest({
|
|
12846
12922
|
method: "POST",
|
|
12847
12923
|
path: "/classify-task",
|
|
@@ -13499,10 +13575,10 @@ function collectCodeDelta(files, opts) {
|
|
|
13499
13575
|
|
|
13500
13576
|
// src/lib/debounce.ts
|
|
13501
13577
|
var import_node_fs9 = require("node:fs");
|
|
13502
|
-
var
|
|
13578
|
+
var import_node_crypto5 = require("node:crypto");
|
|
13503
13579
|
function scopedFile(base, sessionId) {
|
|
13504
13580
|
if (!sessionId) return base;
|
|
13505
|
-
return `${base}.${(0,
|
|
13581
|
+
return `${base}.${(0, import_node_crypto5.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
|
|
13506
13582
|
}
|
|
13507
13583
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
13508
13584
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
@@ -13543,7 +13619,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
13543
13619
|
return "No files modified since last analysis";
|
|
13544
13620
|
}
|
|
13545
13621
|
function computeContentHash(files) {
|
|
13546
|
-
const hash = (0,
|
|
13622
|
+
const hash = (0, import_node_crypto5.createHash)("sha1");
|
|
13547
13623
|
const sorted = [...files].sort();
|
|
13548
13624
|
for (const f of sorted) {
|
|
13549
13625
|
const resolved = resolveFile(f) ?? f;
|
|
@@ -13931,14 +14007,14 @@ function cleanStaleSnapshots(dir, keepSet) {
|
|
|
13931
14007
|
// src/lib/baseline.ts
|
|
13932
14008
|
var import_node_fs13 = require("node:fs");
|
|
13933
14009
|
var import_node_path13 = require("node:path");
|
|
13934
|
-
var
|
|
14010
|
+
var import_node_crypto6 = require("node:crypto");
|
|
13935
14011
|
var BASELINE_VERSION = 1;
|
|
13936
14012
|
var BASELINE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
13937
14013
|
var MIRROR_MAX_BYTES = 2 * 1024 * 1024;
|
|
13938
14014
|
var DEFAULT_SESSION_KEY = "_default";
|
|
13939
14015
|
function sessionKey(sessionId) {
|
|
13940
14016
|
if (!sessionId) return DEFAULT_SESSION_KEY;
|
|
13941
|
-
return (0,
|
|
14017
|
+
return (0, import_node_crypto6.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
13942
14018
|
}
|
|
13943
14019
|
function sessionDir(key) {
|
|
13944
14020
|
return (0, import_node_path13.join)(projectPath(BASELINE_DIR), key);
|
|
@@ -14120,13 +14196,57 @@ function pruneOldBaselines() {
|
|
|
14120
14196
|
}
|
|
14121
14197
|
}
|
|
14122
14198
|
|
|
14199
|
+
// src/lib/task-context.ts
|
|
14200
|
+
var import_node_child_process9 = require("node:child_process");
|
|
14201
|
+
var CLOSING_RE = /\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?)\b[\s:]*#(\d+)/i;
|
|
14202
|
+
var BRANCH_RE = /(?:^|[/_-])(?:issue|gh|fix)[-_/]?(\d+)\b/i;
|
|
14203
|
+
function parseLinkedIssue(sources) {
|
|
14204
|
+
for (const c of sources.commits ?? []) {
|
|
14205
|
+
const m = CLOSING_RE.exec(c);
|
|
14206
|
+
if (m) return { issue: parseInt(m[2], 10), via: `commit:${m[1].toLowerCase()}` };
|
|
14207
|
+
}
|
|
14208
|
+
if (sources.branch) {
|
|
14209
|
+
const m = BRANCH_RE.exec(sources.branch);
|
|
14210
|
+
if (m) return { issue: parseInt(m[1], 10), via: "branch" };
|
|
14211
|
+
}
|
|
14212
|
+
return null;
|
|
14213
|
+
}
|
|
14214
|
+
function safeExec(cmd, timeout) {
|
|
14215
|
+
try {
|
|
14216
|
+
return (0, import_node_child_process9.execSync)(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout }).trim();
|
|
14217
|
+
} catch {
|
|
14218
|
+
return "";
|
|
14219
|
+
}
|
|
14220
|
+
}
|
|
14221
|
+
function defaultGhFetch(issue) {
|
|
14222
|
+
const raw = safeExec(`gh issue view ${issue} --json title,body`, 5e3);
|
|
14223
|
+
if (!raw) return null;
|
|
14224
|
+
try {
|
|
14225
|
+
const j = JSON.parse(raw);
|
|
14226
|
+
return j.title ? { title: j.title, body: j.body ?? "" } : null;
|
|
14227
|
+
} catch {
|
|
14228
|
+
return null;
|
|
14229
|
+
}
|
|
14230
|
+
}
|
|
14231
|
+
function resolveTaskContext(opts) {
|
|
14232
|
+
const branch = opts?.branch ?? safeExec("git rev-parse --abbrev-ref HEAD", 3e3);
|
|
14233
|
+
const commits = opts?.commits ?? safeExec("git log -5 --format=%s%n%b", 3e3).split("\n").map((l) => l.trim()).filter(Boolean);
|
|
14234
|
+
const linked = parseLinkedIssue({ branch, commits });
|
|
14235
|
+
if (!linked) return null;
|
|
14236
|
+
const issue = (opts?.ghFetch ?? defaultGhFetch)(linked.issue);
|
|
14237
|
+
if (!issue) return null;
|
|
14238
|
+
const body = (issue.body ?? "").slice(0, 4e3).trim();
|
|
14239
|
+
const goal = `[#${linked.issue}] ${issue.title}${body ? "\n\n" + body : ""}`;
|
|
14240
|
+
return { number: linked.issue, title: issue.title, goal, via: linked.via };
|
|
14241
|
+
}
|
|
14242
|
+
|
|
14123
14243
|
// src/lib/offline.ts
|
|
14124
14244
|
var import_node_fs14 = require("node:fs");
|
|
14125
|
-
var
|
|
14245
|
+
var import_node_crypto7 = require("node:crypto");
|
|
14126
14246
|
function cacheRequest(body) {
|
|
14127
14247
|
try {
|
|
14128
14248
|
(0, import_node_fs14.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
14129
|
-
const suffix = (0,
|
|
14249
|
+
const suffix = (0, import_node_crypto7.randomBytes)(4).toString("hex");
|
|
14130
14250
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
14131
14251
|
(0, import_node_fs14.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(body));
|
|
14132
14252
|
} catch {
|
|
@@ -14331,6 +14451,30 @@ function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPromp
|
|
|
14331
14451
|
}
|
|
14332
14452
|
return "standard";
|
|
14333
14453
|
}
|
|
14454
|
+
var FILE_MUTATE_RE = /(?:^|[\s|&;(`])(?:sed\s+-i|perl\s+-i|awk\b|tee\b|dd\b|cp\b|mv\b|ln\b|install\b|touch\b|patch\b|git\s+(?:apply|am)\b|cargo\s+build|go\s+generate|make\b|--write\b|--fix\b|--in-place\b)|>>?(?![&>])/i;
|
|
14455
|
+
var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
|
|
14456
|
+
var READ_ONLY_RE = /^\s*(?:git\s+(?:status|diff|log|show|branch|remote|config|rev-parse|ls-files|blame|describe)|ls|cat|head|tail|less|grep|rg|find|pwd|echo|printf|wc|which|type|tree|stat|file|env|printenv|date|whoami)\b/i;
|
|
14457
|
+
var CHAIN_RE = /&&|\||;|\$\(|\x60/;
|
|
14458
|
+
function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
|
|
14459
|
+
if (!actionSummary) return sessionAuthoredCode;
|
|
14460
|
+
if ((actionSummary.subagents ?? 0) > 0) return true;
|
|
14461
|
+
if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
|
|
14462
|
+
const commands = actionSummary.commands ?? [];
|
|
14463
|
+
if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
|
|
14464
|
+
if (sessionAuthoredCode) {
|
|
14465
|
+
const allSafe = commands.length > 0 && commands.every(
|
|
14466
|
+
(c) => !CHAIN_RE.test(c) && (GIT_PLUMBING_RE.test(c) || READ_ONLY_RE.test(c))
|
|
14467
|
+
);
|
|
14468
|
+
if (!allSafe) return true;
|
|
14469
|
+
}
|
|
14470
|
+
return false;
|
|
14471
|
+
}
|
|
14472
|
+
function scopeToAuthored(files, actionSummary) {
|
|
14473
|
+
if (!actionSummary) return { files, signal: "no-transcript" };
|
|
14474
|
+
const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
|
|
14475
|
+
if (touched.length === 0) return { files: [], signal: "none-authored" };
|
|
14476
|
+
return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
|
|
14477
|
+
}
|
|
14334
14478
|
function narrowToAgentAuthored(files, actionSummary) {
|
|
14335
14479
|
if (!actionSummary) return files;
|
|
14336
14480
|
const touched = [
|
|
@@ -14533,6 +14677,7 @@ function buildSummary(lines) {
|
|
|
14533
14677
|
searches++;
|
|
14534
14678
|
break;
|
|
14535
14679
|
case "Agent":
|
|
14680
|
+
case "Task":
|
|
14536
14681
|
subagents++;
|
|
14537
14682
|
break;
|
|
14538
14683
|
case "WebFetch":
|
|
@@ -14585,19 +14730,48 @@ function addPath(set, rawPath) {
|
|
|
14585
14730
|
function sanitizeCommand(rawCmd) {
|
|
14586
14731
|
if (typeof rawCmd !== "string" || !rawCmd) return null;
|
|
14587
14732
|
let cmd = rawCmd.split("\n")[0];
|
|
14733
|
+
let cut = -1;
|
|
14734
|
+
let marker = "";
|
|
14588
14735
|
for (const sep of [" | ", " > ", " >> ", " 2>", " && ", " ; "]) {
|
|
14589
14736
|
const idx = cmd.indexOf(sep);
|
|
14590
|
-
if (idx > 0
|
|
14737
|
+
if (idx > 0 && (cut === -1 || idx < cut)) {
|
|
14738
|
+
cut = idx;
|
|
14739
|
+
marker = sep.trim();
|
|
14740
|
+
}
|
|
14591
14741
|
}
|
|
14742
|
+
if (cut > -1) cmd = cmd.slice(0, cut);
|
|
14592
14743
|
if (cmd.length > MAX_COMMAND_CHARS) {
|
|
14593
14744
|
cmd = cmd.slice(0, MAX_COMMAND_CHARS);
|
|
14594
14745
|
}
|
|
14595
|
-
|
|
14746
|
+
cmd = cmd.trim();
|
|
14747
|
+
if (marker) cmd = cmd ? `${cmd} ${marker}` : marker;
|
|
14748
|
+
return cmd || null;
|
|
14596
14749
|
}
|
|
14597
14750
|
function capArray(set, max) {
|
|
14598
14751
|
return Array.from(set).slice(0, max);
|
|
14599
14752
|
}
|
|
14600
14753
|
|
|
14754
|
+
// src/lib/run-mode.ts
|
|
14755
|
+
function parseAutonomousEnv(raw) {
|
|
14756
|
+
if (raw === void 0) return void 0;
|
|
14757
|
+
const v = raw.trim().toLowerCase();
|
|
14758
|
+
if (v === "") return void 0;
|
|
14759
|
+
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
14760
|
+
return true;
|
|
14761
|
+
}
|
|
14762
|
+
function resolveRunMode(inputs = {}) {
|
|
14763
|
+
if (inputs.autonomousFlag === true) return "autonomous";
|
|
14764
|
+
if (inputs.autonomousFlag === false) return "interactive";
|
|
14765
|
+
const env = inputs.env ?? process.env;
|
|
14766
|
+
const envDecision = parseAutonomousEnv(env.VERITY_AUTONOMOUS);
|
|
14767
|
+
if (envDecision !== void 0) return envDecision ? "autonomous" : "interactive";
|
|
14768
|
+
const isTTY = inputs.isTTY ?? Boolean(process.stdin?.isTTY);
|
|
14769
|
+
return isTTY ? "interactive" : "autonomous";
|
|
14770
|
+
}
|
|
14771
|
+
function isExplicitlyAutonomous(env = process.env) {
|
|
14772
|
+
return parseAutonomousEnv(env.VERITY_AUTONOMOUS) === true || parseAutonomousEnv(env.CI) === true || parseAutonomousEnv(env.GITHUB_ACTIONS) === true;
|
|
14773
|
+
}
|
|
14774
|
+
|
|
14601
14775
|
// src/lib/seed-runner.ts
|
|
14602
14776
|
var import_promises12 = require("node:fs/promises");
|
|
14603
14777
|
var import_node_fs18 = require("node:fs");
|
|
@@ -15012,7 +15186,10 @@ async function runAnalyze(opts, globals) {
|
|
|
15012
15186
|
}
|
|
15013
15187
|
const { assistantMessage: assistantResponse, stopReason, transcriptPath, sessionId } = await readStopHookStdin();
|
|
15014
15188
|
const actionSummary = transcriptPath ? await extractActionSummary(transcriptPath) : null;
|
|
15015
|
-
const
|
|
15189
|
+
const tokenResult = await resolveToken(globals.token);
|
|
15190
|
+
const scopeToken = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
15191
|
+
const rawSessionId = sessionId || process.env.CLAUDE_SESSION_ID || void 0;
|
|
15192
|
+
const baselineSessionId = sessionScopeKey(scopeToken, rawSessionId);
|
|
15016
15193
|
const baseline = readBaseline(baselineSessionId);
|
|
15017
15194
|
if (baseline) {
|
|
15018
15195
|
logEvent("baseline_loaded", {
|
|
@@ -15030,7 +15207,7 @@ async function runAnalyze(opts, globals) {
|
|
|
15030
15207
|
passAndExit("No analyzable files changed");
|
|
15031
15208
|
}
|
|
15032
15209
|
const allForReview = Array.from(/* @__PURE__ */ new Set([...analyzable, ...reviewable]));
|
|
15033
|
-
const conversation = await readAndClearConversationBuffer(
|
|
15210
|
+
const conversation = await readAndClearConversationBuffer(baselineSessionId);
|
|
15034
15211
|
const specs = discoverSpecs();
|
|
15035
15212
|
const plans = discoverPlans();
|
|
15036
15213
|
const latestPrompt = conversation?.prompts?.[conversation.prompts.length - 1]?.prompt ?? "";
|
|
@@ -15044,7 +15221,6 @@ async function runAnalyze(opts, globals) {
|
|
|
15044
15221
|
if (isReflectionQuestion(assistantResponse) && !agentAuthoredCodeThisTurn) {
|
|
15045
15222
|
passAndExit("Reflection-prompt turn \u2014 skipping analysis");
|
|
15046
15223
|
}
|
|
15047
|
-
const tokenResult = await resolveToken(globals.token);
|
|
15048
15224
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
15049
15225
|
if (!tokenResult.ok || !urlResult.ok) {
|
|
15050
15226
|
localOnlyAndExit(runLocalStatic(analyzable, securityFiles, baseline, !!opts.skipStatic));
|
|
@@ -15138,8 +15314,11 @@ async function runAnalyze(opts, globals) {
|
|
|
15138
15314
|
}
|
|
15139
15315
|
contentHash = hashResult.hash;
|
|
15140
15316
|
if (analysisMode !== "plan") {
|
|
15141
|
-
const
|
|
15142
|
-
|
|
15317
|
+
const scoped = scopeToAuthored(allForReview, actionSummary);
|
|
15318
|
+
if (scoped.signal === "none-authored" && !hasNonEditAuthorship(actionSummary, sessionAuthoredCode)) {
|
|
15319
|
+
passAndExit("No agent-authored code this turn \u2014 working-tree changes were not authored by this session");
|
|
15320
|
+
}
|
|
15321
|
+
const baseForReview = scoped.signal === "authored" && scoped.files.length > 0 ? scoped.files : allForReview;
|
|
15143
15322
|
const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
|
|
15144
15323
|
if (!opts.skipStatic && isCodacyAvailable()) {
|
|
15145
15324
|
let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
@@ -15269,7 +15448,9 @@ async function runAnalyze(opts, globals) {
|
|
|
15269
15448
|
if (snapshotResult.has_snapshots && snapshotResult.diffs.length > 0) {
|
|
15270
15449
|
requestBody.snapshot_diffs = snapshotResult.diffs;
|
|
15271
15450
|
}
|
|
15272
|
-
const
|
|
15451
|
+
const noHumanPrompt = (conversation?.prompts?.length ?? 0) === 0;
|
|
15452
|
+
const w4Task = noHumanPrompt && isExplicitlyAutonomous() ? resolveTaskContext() : null;
|
|
15453
|
+
const hasIntent = (conversation?.prompts?.length ?? 0) > 0 || specs.length > 0 || plans.length > 0 || !!assistantResponse || !!w4Task;
|
|
15273
15454
|
if (hasIntent) {
|
|
15274
15455
|
const intentContext = {};
|
|
15275
15456
|
if (conversation && conversation.prompts.length > 0) {
|
|
@@ -15284,6 +15465,10 @@ async function runAnalyze(opts, globals) {
|
|
|
15284
15465
|
intentContext.recent_commits = conversation.recent_commits;
|
|
15285
15466
|
}
|
|
15286
15467
|
}
|
|
15468
|
+
if (w4Task && !intentContext.user_prompt) {
|
|
15469
|
+
intentContext.user_prompt = w4Task.goal;
|
|
15470
|
+
logEvent("w4_issue_anchor", { issue: w4Task.number, via: w4Task.via });
|
|
15471
|
+
}
|
|
15287
15472
|
if (assistantResponse) {
|
|
15288
15473
|
const cap = analysisMode === "plan" ? MAX_ASSISTANT_RESPONSE_CHARS_PLAN : MAX_ASSISTANT_RESPONSE_CHARS_DEFAULT;
|
|
15289
15474
|
intentContext.assistant_response = assistantResponse.length > cap ? assistantResponse.slice(0, cap) : assistantResponse;
|
|
@@ -15576,7 +15761,10 @@ function registerBaselineCommands(program2) {
|
|
|
15576
15761
|
}
|
|
15577
15762
|
}
|
|
15578
15763
|
}
|
|
15579
|
-
const
|
|
15764
|
+
const authForScope = await resolveToken(program2.opts().token);
|
|
15765
|
+
const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
|
|
15766
|
+
const scopeSession = sessionId || process.env.CLAUDE_SESSION_ID || void 0;
|
|
15767
|
+
const result = captureBaseline({ sessionId: sessionScopeKey(scopeToken, scopeSession), source });
|
|
15580
15768
|
logEvent("baseline_capture", {
|
|
15581
15769
|
created: result.created,
|
|
15582
15770
|
source: source ?? null,
|
|
@@ -16022,20 +16210,20 @@ function writeBlockMessage(moment, response) {
|
|
|
16022
16210
|
var import_node_fs24 = require("node:fs");
|
|
16023
16211
|
var import_promises13 = require("node:fs/promises");
|
|
16024
16212
|
var import_node_path19 = require("node:path");
|
|
16025
|
-
var
|
|
16213
|
+
var import_node_child_process11 = require("node:child_process");
|
|
16026
16214
|
var readline2 = __toESM(require("node:readline/promises"));
|
|
16027
16215
|
|
|
16028
16216
|
// src/commands/migrate.ts
|
|
16029
16217
|
var import_node_fs23 = require("node:fs");
|
|
16030
16218
|
var import_node_path18 = require("node:path");
|
|
16031
|
-
var
|
|
16219
|
+
var import_node_child_process10 = require("node:child_process");
|
|
16032
16220
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
16033
16221
|
function defaultNpmRemover(pkg) {
|
|
16034
|
-
(0,
|
|
16222
|
+
(0, import_node_child_process10.execSync)(`npm rm -g ${pkg}`, { stdio: "pipe", timeout: 12e4 });
|
|
16035
16223
|
}
|
|
16036
16224
|
function isGitTracked(cwd, relPath) {
|
|
16037
16225
|
try {
|
|
16038
|
-
(0,
|
|
16226
|
+
(0, import_node_child_process10.execSync)(`git ls-files --error-unmatch ${relPath}`, { cwd, stdio: "pipe" });
|
|
16039
16227
|
return true;
|
|
16040
16228
|
} catch {
|
|
16041
16229
|
return false;
|
|
@@ -16043,7 +16231,7 @@ function isGitTracked(cwd, relPath) {
|
|
|
16043
16231
|
}
|
|
16044
16232
|
function isGitRepo(cwd) {
|
|
16045
16233
|
try {
|
|
16046
|
-
(0,
|
|
16234
|
+
(0, import_node_child_process10.execSync)("git rev-parse --is-inside-work-tree", { cwd, stdio: "pipe" });
|
|
16047
16235
|
return true;
|
|
16048
16236
|
} catch {
|
|
16049
16237
|
return false;
|
|
@@ -16082,7 +16270,7 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
16082
16270
|
);
|
|
16083
16271
|
}
|
|
16084
16272
|
try {
|
|
16085
|
-
(0,
|
|
16273
|
+
(0, import_node_child_process10.execSync)("git mv .gate .verity", { cwd: root, stdio: "pipe" });
|
|
16086
16274
|
actions.push("Moved .gate/ \u2192 .verity/ (git mv, staged)");
|
|
16087
16275
|
moved = true;
|
|
16088
16276
|
} catch {
|
|
@@ -16161,7 +16349,7 @@ function migrateStandardFile(root, actions) {
|
|
|
16161
16349
|
let moved = false;
|
|
16162
16350
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
16163
16351
|
try {
|
|
16164
|
-
(0,
|
|
16352
|
+
(0, import_node_child_process10.execSync)("git mv GATE.md VERITY.md", { cwd: root, stdio: "pipe" });
|
|
16165
16353
|
moved = true;
|
|
16166
16354
|
} catch {
|
|
16167
16355
|
}
|
|
@@ -16217,7 +16405,7 @@ function readFileSyncSafe(path) {
|
|
|
16217
16405
|
}
|
|
16218
16406
|
function hasStagedChanges(root) {
|
|
16219
16407
|
try {
|
|
16220
|
-
(0,
|
|
16408
|
+
(0, import_node_child_process10.execSync)("git diff --cached --quiet", { cwd: root, stdio: "pipe" });
|
|
16221
16409
|
return false;
|
|
16222
16410
|
} catch {
|
|
16223
16411
|
return true;
|
|
@@ -16313,30 +16501,47 @@ async function promptYes(question) {
|
|
|
16313
16501
|
rl.close();
|
|
16314
16502
|
}
|
|
16315
16503
|
}
|
|
16316
|
-
async function
|
|
16317
|
-
const existing = await resolveToken();
|
|
16318
|
-
if (existing.ok)
|
|
16319
|
-
|
|
16320
|
-
|
|
16321
|
-
|
|
16322
|
-
|
|
16504
|
+
async function confirmExistingLogin(serviceUrl, opts) {
|
|
16505
|
+
const existing = await resolveToken(opts.token);
|
|
16506
|
+
if (!existing.ok) return "drive-login";
|
|
16507
|
+
const who = await whoami(existing.data.token, serviceUrl, opts.verbose);
|
|
16508
|
+
if (who.ok && who.data.logged_in) {
|
|
16509
|
+
printInfo(`Logged in as ${who.data.email ?? `user #${who.data.user_id}`} \u2713 \u2014 runs & memory sync to Verity.`);
|
|
16510
|
+
return "handled";
|
|
16511
|
+
}
|
|
16512
|
+
if (!who.ok) {
|
|
16513
|
+
if (existing.data.userId != null) {
|
|
16514
|
+
printInfo(`Logged in as ${existing.data.email ?? `user #${existing.data.userId}`} (cached \u2014 could not reach the Verity service). \u2713`);
|
|
16515
|
+
} else {
|
|
16516
|
+
printInfo("Could not confirm your login state with the service; continuing with your existing token.");
|
|
16517
|
+
printInfo(` (${who.error})`);
|
|
16323
16518
|
}
|
|
16324
|
-
|
|
16325
|
-
|
|
16326
|
-
|
|
16327
|
-
|
|
16328
|
-
|
|
16329
|
-
|
|
16330
|
-
|
|
16519
|
+
return "handled";
|
|
16520
|
+
}
|
|
16521
|
+
console.log("");
|
|
16522
|
+
printWarn("You are NOT logged in \u2014 this project has only an anonymous token.");
|
|
16523
|
+
printInfo(" The gate still runs, but no runs are saved and Verity keeps no memory of this project.");
|
|
16524
|
+
printInfo(" Log in below to unlock run history, trends, and cloud memory (strongly recommended).");
|
|
16525
|
+
return "drive-login";
|
|
16526
|
+
}
|
|
16527
|
+
async function runOptionalAuth(resolution, opts = {}) {
|
|
16528
|
+
let serviceUrl = resolution?.url ?? DEFAULT_SERVICE_URL;
|
|
16529
|
+
let healed = false;
|
|
16530
|
+
if (resolution) {
|
|
16531
|
+
const heal = await maybeHealServiceUrl(resolution, opts.verbose);
|
|
16532
|
+
serviceUrl = heal.serviceUrl;
|
|
16533
|
+
healed = heal.healed;
|
|
16534
|
+
if (healed) {
|
|
16535
|
+
printInfo(" Log in below to re-register this project and repair .verity/credentials.");
|
|
16331
16536
|
}
|
|
16332
|
-
|
|
16333
|
-
|
|
16334
|
-
|
|
16335
|
-
|
|
16537
|
+
}
|
|
16538
|
+
if (!healed) {
|
|
16539
|
+
const state = await confirmExistingLogin(serviceUrl, opts);
|
|
16540
|
+
if (state === "handled") return;
|
|
16336
16541
|
}
|
|
16337
16542
|
let remote = "";
|
|
16338
16543
|
try {
|
|
16339
|
-
remote = (0,
|
|
16544
|
+
remote = (0, import_node_child_process11.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
16340
16545
|
} catch {
|
|
16341
16546
|
}
|
|
16342
16547
|
const localOnlyNote = () => {
|
|
@@ -16369,7 +16574,7 @@ async function runOptionalAuth(serviceUrl) {
|
|
|
16369
16574
|
}
|
|
16370
16575
|
const projectName = parseRemote(remote)?.repo ?? (0, import_node_path19.basename)(process.cwd());
|
|
16371
16576
|
printInfo("Authenticating with GitHub\u2026");
|
|
16372
|
-
const result = await registerProject({ projectName, remote, serviceUrl });
|
|
16577
|
+
const result = await registerProject({ projectName, remote, serviceUrl, verbose: opts.verbose });
|
|
16373
16578
|
if (result.ok) {
|
|
16374
16579
|
const who = result.data.email ?? (result.data.userId != null ? `user #${result.data.userId}` : null);
|
|
16375
16580
|
printInfo(`Logged in${who ? ` as ${who}` : ""} \u2713 \u2014 runs, history, and cloud memory now sync to Verity.`);
|
|
@@ -16432,30 +16637,30 @@ function registerInitCommand(program2) {
|
|
|
16432
16637
|
}
|
|
16433
16638
|
printInfo(` Node.js ${nodeVersion} \u2713`);
|
|
16434
16639
|
try {
|
|
16435
|
-
const gitVersion = (0,
|
|
16640
|
+
const gitVersion = (0, import_node_child_process11.execSync)("git --version", { encoding: "utf-8" }).trim();
|
|
16436
16641
|
printInfo(` ${gitVersion} \u2713`);
|
|
16437
16642
|
} catch {
|
|
16438
16643
|
printError("git is required but not installed. Install from https://git-scm.com");
|
|
16439
16644
|
process.exit(1);
|
|
16440
16645
|
}
|
|
16441
16646
|
try {
|
|
16442
|
-
(0,
|
|
16647
|
+
(0, import_node_child_process11.execSync)("which claude", { encoding: "utf-8" });
|
|
16443
16648
|
printInfo(" Claude Code \u2713");
|
|
16444
16649
|
} catch {
|
|
16445
16650
|
printWarn(" Claude Code not found \u2014 hooks will be configured but need Claude Code to run.");
|
|
16446
16651
|
}
|
|
16447
16652
|
try {
|
|
16448
|
-
(0,
|
|
16653
|
+
(0, import_node_child_process11.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
|
|
16449
16654
|
printInfo(" @codacy/analysis-cli \u2713");
|
|
16450
16655
|
} catch {
|
|
16451
16656
|
printInfo(" Installing @codacy/analysis-cli...");
|
|
16452
16657
|
try {
|
|
16453
|
-
(0,
|
|
16658
|
+
(0, import_node_child_process11.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
|
|
16454
16659
|
printInfo(" @codacy/analysis-cli installed \u2713");
|
|
16455
16660
|
} catch {
|
|
16456
16661
|
try {
|
|
16457
16662
|
printWarn(" Retrying with sudo...");
|
|
16458
|
-
(0,
|
|
16663
|
+
(0, import_node_child_process11.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
|
|
16459
16664
|
printInfo(" @codacy/analysis-cli installed \u2713");
|
|
16460
16665
|
} catch {
|
|
16461
16666
|
printWarn(" Could not install @codacy/analysis-cli automatically.");
|
|
@@ -16523,8 +16728,11 @@ function registerInitCommand(program2) {
|
|
|
16523
16728
|
console.log("");
|
|
16524
16729
|
try {
|
|
16525
16730
|
const globals = program2.opts();
|
|
16526
|
-
const urlResult = await
|
|
16527
|
-
await runOptionalAuth(urlResult.ok ? urlResult.data :
|
|
16731
|
+
const urlResult = await resolveServiceUrlDetailed(globals.serviceUrl);
|
|
16732
|
+
await runOptionalAuth(urlResult.ok ? urlResult.data : null, {
|
|
16733
|
+
token: globals.token,
|
|
16734
|
+
verbose: globals.verbose
|
|
16735
|
+
});
|
|
16528
16736
|
} catch (err) {
|
|
16529
16737
|
printWarn(`Authentication step skipped: ${err.message}`);
|
|
16530
16738
|
}
|
|
@@ -16894,24 +17102,6 @@ function registerResetCommand(program2) {
|
|
|
16894
17102
|
});
|
|
16895
17103
|
}
|
|
16896
17104
|
|
|
16897
|
-
// src/lib/run-mode.ts
|
|
16898
|
-
function parseAutonomousEnv(raw) {
|
|
16899
|
-
if (raw === void 0) return void 0;
|
|
16900
|
-
const v = raw.trim().toLowerCase();
|
|
16901
|
-
if (v === "") return void 0;
|
|
16902
|
-
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
16903
|
-
return true;
|
|
16904
|
-
}
|
|
16905
|
-
function resolveRunMode(inputs = {}) {
|
|
16906
|
-
if (inputs.autonomousFlag === true) return "autonomous";
|
|
16907
|
-
if (inputs.autonomousFlag === false) return "interactive";
|
|
16908
|
-
const env = inputs.env ?? process.env;
|
|
16909
|
-
const envDecision = parseAutonomousEnv(env.VERITY_AUTONOMOUS);
|
|
16910
|
-
if (envDecision !== void 0) return envDecision ? "autonomous" : "interactive";
|
|
16911
|
-
const isTTY = inputs.isTTY ?? Boolean(process.stdin?.isTTY);
|
|
16912
|
-
return isTTY ? "interactive" : "autonomous";
|
|
16913
|
-
}
|
|
16914
|
-
|
|
16915
17105
|
// src/commands/reflect.ts
|
|
16916
17106
|
function registerReflectCommand(program2) {
|
|
16917
17107
|
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) => {
|
|
@@ -17273,7 +17463,7 @@ function registerTelemetryCommands(program2) {
|
|
|
17273
17463
|
}
|
|
17274
17464
|
|
|
17275
17465
|
// src/cli.ts
|
|
17276
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.
|
|
17466
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.28.1").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
|
|
17277
17467
|
registerAuthCommands(program);
|
|
17278
17468
|
registerLoginCommand(program);
|
|
17279
17469
|
registerHooksCommands(program);
|
package/package.json
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codacy/verity-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.1",
|
|
4
4
|
"description": "CLI for Verity quality gate service",
|
|
5
5
|
"homepage": "https://verity.md",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/codacy/verity.git"
|
|
9
|
-
},
|
|
10
6
|
"bugs": {
|
|
11
7
|
"url": "https://github.com/codacy/verity/issues"
|
|
12
8
|
},
|