@codacy/verity-cli 0.35.0-experimental.2d2f4df → 0.35.0-experimental.ce90a7b
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 +208 -30
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -16931,8 +16931,156 @@ function terminalUrl(value) {
|
|
|
16931
16931
|
return /^https?:\/\/\S+$/.test(clean2) ? clean2 : "";
|
|
16932
16932
|
}
|
|
16933
16933
|
|
|
16934
|
+
// src/lib/standard-content.ts
|
|
16935
|
+
var MAX_STANDARD_BYTES = 256 * 1024;
|
|
16936
|
+
var MAX_DEPTH = 12;
|
|
16937
|
+
var MAX_ID_LENGTH = 120;
|
|
16938
|
+
var MAX_STRING_LENGTH = 8 * 1024;
|
|
16939
|
+
var MAX_VERITYIGNORE_BYTES = 64 * 1024;
|
|
16940
|
+
var TOP_KEYS = /* @__PURE__ */ new Set([
|
|
16941
|
+
"knowledge_spec",
|
|
16942
|
+
"quality_dimensions",
|
|
16943
|
+
"security_patterns",
|
|
16944
|
+
"custom_patterns",
|
|
16945
|
+
"process_constraints",
|
|
16946
|
+
"tool_configuration",
|
|
16947
|
+
"created_by",
|
|
16948
|
+
"version",
|
|
16949
|
+
"verityignore"
|
|
16950
|
+
]);
|
|
16951
|
+
var KNOWLEDGE_SPEC_KEYS = /* @__PURE__ */ new Set([
|
|
16952
|
+
"project_name",
|
|
16953
|
+
"languages",
|
|
16954
|
+
"frameworks",
|
|
16955
|
+
"architecture",
|
|
16956
|
+
"test_framework",
|
|
16957
|
+
"build_system",
|
|
16958
|
+
"git_remote",
|
|
16959
|
+
"runtime_notes"
|
|
16960
|
+
]);
|
|
16961
|
+
var PATTERN_KEYS = /* @__PURE__ */ new Set([
|
|
16962
|
+
"id",
|
|
16963
|
+
"severity",
|
|
16964
|
+
"description",
|
|
16965
|
+
"rationale",
|
|
16966
|
+
"enforced_by",
|
|
16967
|
+
"cwe",
|
|
16968
|
+
"paths",
|
|
16969
|
+
"signal",
|
|
16970
|
+
"note",
|
|
16971
|
+
"notes",
|
|
16972
|
+
"file_exclusions"
|
|
16973
|
+
]);
|
|
16974
|
+
var DIMENSION_KEYS = /* @__PURE__ */ new Set(["id", "description", "signals"]);
|
|
16975
|
+
var SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "med", "low"]);
|
|
16976
|
+
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
16977
|
+
var PRINTABLE = /^[^\u0000-\u001f\u007f]+$/;
|
|
16978
|
+
var CONTROL_EXCEPT_WHITESPACE = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/;
|
|
16979
|
+
var fail = (error) => ({ ok: false, error });
|
|
16980
|
+
function checkValues(v, path, depth) {
|
|
16981
|
+
if (depth > MAX_DEPTH) return fail(`content is nested deeper than ${MAX_DEPTH} levels (at ${path})`);
|
|
16982
|
+
if (typeof v === "string") {
|
|
16983
|
+
if (path === "verityignore") return { ok: true };
|
|
16984
|
+
if (v.length > MAX_STRING_LENGTH) return fail(`${path} is longer than ${MAX_STRING_LENGTH} characters`);
|
|
16985
|
+
if (CONTROL_EXCEPT_WHITESPACE.test(v)) return fail(`${path} contains a control character`);
|
|
16986
|
+
return { ok: true };
|
|
16987
|
+
}
|
|
16988
|
+
if (Array.isArray(v)) {
|
|
16989
|
+
for (const [i2, x] of v.entries()) {
|
|
16990
|
+
const r = checkValues(x, `${path}[${i2}]`, depth + 1);
|
|
16991
|
+
if (!r.ok) return r;
|
|
16992
|
+
}
|
|
16993
|
+
return { ok: true };
|
|
16994
|
+
}
|
|
16995
|
+
if (isPlainObject(v)) {
|
|
16996
|
+
for (const [k, x] of Object.entries(v)) {
|
|
16997
|
+
if (k.length > MAX_ID_LENGTH || !PRINTABLE.test(k)) return fail(`${path} has a key that is not printable text of 1 to ${MAX_ID_LENGTH} characters`);
|
|
16998
|
+
const r = checkValues(x, path ? `${path}.${k}` : k, depth + 1);
|
|
16999
|
+
if (!r.ok) return r;
|
|
17000
|
+
}
|
|
17001
|
+
}
|
|
17002
|
+
return { ok: true };
|
|
17003
|
+
}
|
|
17004
|
+
function unknownKey(obj, allowed, where2) {
|
|
17005
|
+
const extra = Object.keys(obj).find((k) => !allowed.has(k));
|
|
17006
|
+
return extra === void 0 ? null : fail(`${where2}.${extra} is not a known field`);
|
|
17007
|
+
}
|
|
17008
|
+
function checkEntries(list2, section, allowed, withSeverity) {
|
|
17009
|
+
for (const [i2, entry] of list2.entries()) {
|
|
17010
|
+
const at = `${section}[${i2}]`;
|
|
17011
|
+
if (!isPlainObject(entry)) return fail(`${at} must be an object`);
|
|
17012
|
+
const extra = unknownKey(entry, allowed, at);
|
|
17013
|
+
if (extra) return extra;
|
|
17014
|
+
const id = entry.id;
|
|
17015
|
+
if (typeof id !== "string" || id.length === 0 || id.length > MAX_ID_LENGTH || !PRINTABLE.test(id)) {
|
|
17016
|
+
return fail(`${at}.id must be printable text of 1 to ${MAX_ID_LENGTH} characters`);
|
|
17017
|
+
}
|
|
17018
|
+
if (withSeverity && "severity" in entry && !SEVERITIES.has(String(entry.severity))) {
|
|
17019
|
+
return fail(`${at}.severity must be one of critical, high, medium, low`);
|
|
17020
|
+
}
|
|
17021
|
+
for (const key of ["enforced_by", "cwe", "paths", "file_exclusions"]) {
|
|
17022
|
+
if (key in entry && !Array.isArray(entry[key])) return fail(`${at}.${key} must be an array`);
|
|
17023
|
+
}
|
|
17024
|
+
}
|
|
17025
|
+
return { ok: true };
|
|
17026
|
+
}
|
|
17027
|
+
function validateStandardContent(content, opts = {}) {
|
|
17028
|
+
const requireAll = opts.requireAll ?? true;
|
|
17029
|
+
if (!isPlainObject(content)) return fail("content is required and must be an object");
|
|
17030
|
+
const size = new TextEncoder().encode(JSON.stringify(content)).length;
|
|
17031
|
+
if (size > MAX_STANDARD_BYTES) return fail(`content is ${size} bytes; the limit is ${MAX_STANDARD_BYTES}`);
|
|
17032
|
+
const values = checkValues(content, "", 0);
|
|
17033
|
+
if (!values.ok) return values;
|
|
17034
|
+
const missing = ["knowledge_spec", "quality_dimensions", "security_patterns", "process_constraints"].filter((k) => !(k in content));
|
|
17035
|
+
if (requireAll && missing.length > 0) return fail(`content is missing required keys: ${missing.join(", ")}`);
|
|
17036
|
+
const extraTop = unknownKey(content, TOP_KEYS, "content");
|
|
17037
|
+
if (extraTop) return extraTop;
|
|
17038
|
+
if ("knowledge_spec" in content) {
|
|
17039
|
+
if (!isPlainObject(content.knowledge_spec)) return fail("knowledge_spec must be an object");
|
|
17040
|
+
const extraSpec = unknownKey(content.knowledge_spec, KNOWLEDGE_SPEC_KEYS, "knowledge_spec");
|
|
17041
|
+
if (extraSpec) return extraSpec;
|
|
17042
|
+
}
|
|
17043
|
+
if ("process_constraints" in content && !isPlainObject(content.process_constraints)) return fail("process_constraints must be an object");
|
|
17044
|
+
if ("tool_configuration" in content && !isPlainObject(content.tool_configuration)) {
|
|
17045
|
+
return fail("tool_configuration must be an object");
|
|
17046
|
+
}
|
|
17047
|
+
if ("quality_dimensions" in content) {
|
|
17048
|
+
if (!Array.isArray(content.quality_dimensions)) return fail("quality_dimensions must be an array");
|
|
17049
|
+
const dims = checkEntries(content.quality_dimensions, "quality_dimensions", DIMENSION_KEYS, false);
|
|
17050
|
+
if (!dims.ok) return dims;
|
|
17051
|
+
}
|
|
17052
|
+
if ("security_patterns" in content) {
|
|
17053
|
+
if (!Array.isArray(content.security_patterns)) return fail("security_patterns must be an array");
|
|
17054
|
+
const sec = checkEntries(content.security_patterns, "security_patterns", PATTERN_KEYS, true);
|
|
17055
|
+
if (!sec.ok) return sec;
|
|
17056
|
+
}
|
|
17057
|
+
if ("custom_patterns" in content) {
|
|
17058
|
+
if (!Array.isArray(content.custom_patterns)) return fail("custom_patterns must be an array");
|
|
17059
|
+
const custom = checkEntries(content.custom_patterns, "custom_patterns", PATTERN_KEYS, true);
|
|
17060
|
+
if (!custom.ok) return custom;
|
|
17061
|
+
}
|
|
17062
|
+
for (const key of ["created_by", "version"]) {
|
|
17063
|
+
if (key in content && content[key] !== null && typeof content[key] !== "string") return fail(`${key} must be a string`);
|
|
17064
|
+
}
|
|
17065
|
+
if ("verityignore" in content) {
|
|
17066
|
+
const v = content.verityignore;
|
|
17067
|
+
if (typeof v !== "string") return fail("verityignore must be a string");
|
|
17068
|
+
if (new TextEncoder().encode(v).length > MAX_VERITYIGNORE_BYTES) {
|
|
17069
|
+
return fail(`verityignore is larger than ${MAX_VERITYIGNORE_BYTES} bytes`);
|
|
17070
|
+
}
|
|
17071
|
+
if (CONTROL_EXCEPT_WHITESPACE.test(v)) return fail("verityignore contains a control character");
|
|
17072
|
+
}
|
|
17073
|
+
return { ok: true };
|
|
17074
|
+
}
|
|
17075
|
+
|
|
16934
17076
|
// src/lib/remote-config.ts
|
|
16935
17077
|
var IGNORE_RIDER = "verityignore";
|
|
17078
|
+
function identifiableStandard(content) {
|
|
17079
|
+
const spec = content.knowledge_spec;
|
|
17080
|
+
const name2 = spec && typeof spec === "object" && !Array.isArray(spec) ? spec.project_name : void 0;
|
|
17081
|
+
const hasList = ["security_patterns", "quality_dimensions", "custom_patterns"].some((k) => Array.isArray(content[k]));
|
|
17082
|
+
return typeof name2 === "string" && name2.trim().length > 0 && hasList;
|
|
17083
|
+
}
|
|
16936
17084
|
async function fetchRemoteSetup(opts) {
|
|
16937
17085
|
const standard = await apiRequest({
|
|
16938
17086
|
method: "GET",
|
|
@@ -16945,19 +17093,32 @@ async function fetchRemoteSetup(opts) {
|
|
|
16945
17093
|
const missing = standard.http_status === 404 && standard.error.startsWith("STANDARD_NOT_FOUND");
|
|
16946
17094
|
return missing ? { status: "none" } : { status: "unavailable", reason: standard.error };
|
|
16947
17095
|
}
|
|
17096
|
+
const d = standard.data;
|
|
17097
|
+
const content = d?.content;
|
|
17098
|
+
if (!d || typeof d.version !== "number" || !Number.isSafeInteger(d.version) || d.version < 1 || typeof content !== "object" || content === null || Array.isArray(content)) {
|
|
17099
|
+
return { status: "unavailable", reason: "the service answered without a Standard" };
|
|
17100
|
+
}
|
|
17101
|
+
const valid = validateStandardContent(content, { requireAll: false });
|
|
17102
|
+
if (!valid.ok) return { status: "unavailable", reason: `the team's Standard on the service is not valid here (${terminalText(valid.error, 200)})` };
|
|
17103
|
+
if (!identifiableStandard(content)) {
|
|
17104
|
+
return { status: "unavailable", reason: "the service answered with a Standard that names no project or holds no rules" };
|
|
17105
|
+
}
|
|
16948
17106
|
return {
|
|
16949
17107
|
status: "found",
|
|
16950
17108
|
standard: {
|
|
16951
|
-
version:
|
|
16952
|
-
content
|
|
16953
|
-
createdBy:
|
|
16954
|
-
createdAt:
|
|
17109
|
+
version: d.version,
|
|
17110
|
+
content,
|
|
17111
|
+
createdBy: typeof d.created_by === "string" ? d.created_by : null,
|
|
17112
|
+
createdAt: typeof d.created_at === "string" ? d.created_at : ""
|
|
16955
17113
|
}
|
|
16956
17114
|
};
|
|
16957
17115
|
}
|
|
16958
17116
|
async function adoptRemoteSetup(found, opts) {
|
|
16959
17117
|
const written = [];
|
|
16960
17118
|
const notes = [];
|
|
17119
|
+
const valid = validateStandardContent(found.standard.content, { requireAll: false });
|
|
17120
|
+
if (!valid.ok) throw new Error(`the team's Standard on the service is not valid here (${terminalText(valid.error, 200)}), so nothing was written`);
|
|
17121
|
+
if (!identifiableStandard(found.standard.content)) throw new Error("the team's Standard on the service names no project or holds no rules, so nothing was written");
|
|
16961
17122
|
const content = { ...found.standard.content };
|
|
16962
17123
|
const rider = typeof content[IGNORE_RIDER] === "string" ? content[IGNORE_RIDER] : null;
|
|
16963
17124
|
delete content[IGNORE_RIDER];
|
|
@@ -17179,7 +17340,7 @@ async function shareLocalStandard(globals) {
|
|
|
17179
17340
|
}
|
|
17180
17341
|
var MAX_WAIT_SECONDS = 600;
|
|
17181
17342
|
async function finishSplitLogin(opts) {
|
|
17182
|
-
function
|
|
17343
|
+
function fail2(status, error, clear) {
|
|
17183
17344
|
if (clear) clearPendingLogin();
|
|
17184
17345
|
printError(`Login failed: ${error}`);
|
|
17185
17346
|
printJson({ status, error });
|
|
@@ -17187,15 +17348,15 @@ async function finishSplitLogin(opts) {
|
|
|
17187
17348
|
}
|
|
17188
17349
|
const wait = Number(String(opts.waitSeconds ?? "100").trim());
|
|
17189
17350
|
if (!Number.isInteger(wait) || wait < 0 || wait > MAX_WAIT_SECONDS) {
|
|
17190
|
-
|
|
17351
|
+
fail2("invalid", `--wait must be a whole number of seconds from 0 to ${MAX_WAIT_SECONDS}`, false);
|
|
17191
17352
|
}
|
|
17192
17353
|
const read2 = readPendingLogin();
|
|
17193
|
-
if (read2.status === "none")
|
|
17194
|
-
if (read2.status === "invalid")
|
|
17195
|
-
if (read2.status === "expired")
|
|
17354
|
+
if (read2.status === "none") fail2("no_pending", 'no sign-in is pending \u2014 run "verity login --start" first', false);
|
|
17355
|
+
if (read2.status === "invalid") fail2("invalid", `the pending sign-in is unusable (${read2.reason}) \u2014 run "verity login --start" again`, true);
|
|
17356
|
+
if (read2.status === "expired") fail2("expired", 'the code expired before it was approved \u2014 run "verity login --start" again', true);
|
|
17196
17357
|
const pending = read2.record;
|
|
17197
17358
|
if (pending.service_url !== opts.serviceUrl) {
|
|
17198
|
-
|
|
17359
|
+
fail2(
|
|
17199
17360
|
"service_changed",
|
|
17200
17361
|
`the sign-in was started for ${pending.service_url}, but this machine now resolves ${opts.serviceUrl} \u2014 run "verity login --start" again`,
|
|
17201
17362
|
true
|
|
@@ -17216,7 +17377,7 @@ async function finishSplitLogin(opts) {
|
|
|
17216
17377
|
});
|
|
17217
17378
|
process.exit(2);
|
|
17218
17379
|
}
|
|
17219
|
-
|
|
17380
|
+
fail2(polled.reason, polled.error, true);
|
|
17220
17381
|
}
|
|
17221
17382
|
clearPendingLogin();
|
|
17222
17383
|
const result = await loginOnce({
|
|
@@ -17225,7 +17386,7 @@ async function finishSplitLogin(opts) {
|
|
|
17225
17386
|
verbose: opts.verbose,
|
|
17226
17387
|
providerToken: polled.data
|
|
17227
17388
|
});
|
|
17228
|
-
if (!result.ok)
|
|
17389
|
+
if (!result.ok) fail2("failed", result.error, false);
|
|
17229
17390
|
const data = result.data;
|
|
17230
17391
|
await reportLoginOutcome(data, { remote: opts.remote || void 0, verbose: opts.verbose });
|
|
17231
17392
|
const shared = await shareLocalStandard({ serviceUrl: opts.serviceUrl, verbose: opts.verbose });
|
|
@@ -24555,7 +24716,7 @@ function fitDoc(text2, budget) {
|
|
|
24555
24716
|
}
|
|
24556
24717
|
var normal = (line2) => line2.trim().toLowerCase().replace(/\s+/g, " ");
|
|
24557
24718
|
function docs(root, files) {
|
|
24558
|
-
const nested = files.filter((f) => NESTED_DOC.test(f) && !NOT_THE_TEAMS.test(f)).sort((a, b) => a.split("/").length - b.split("/").length || a.localeCompare(b));
|
|
24719
|
+
const nested = files.filter((f) => NESTED_DOC.test(f) && !NOT_THE_TEAMS.test(f) && safePath(f) !== null).sort((a, b) => a.split("/").length - b.split("/").length || a.localeCompare(b));
|
|
24559
24720
|
const plan = [
|
|
24560
24721
|
...ROOT_DOCS.map((n2) => [n2, LIMITS.docBytes]),
|
|
24561
24722
|
...nested.map((n2) => [n2, LIMITS.nestedDocBytes]),
|
|
@@ -24650,13 +24811,16 @@ function rulesFrom(content, before) {
|
|
|
24650
24811
|
});
|
|
24651
24812
|
}
|
|
24652
24813
|
async function generateStandard(opts) {
|
|
24814
|
+
if (opts.replaces !== void 0 && (!Number.isSafeInteger(opts.replaces) || opts.replaces < 1)) {
|
|
24815
|
+
return { status: "failed", reason: "the version to replace is not a valid Standard version" };
|
|
24816
|
+
}
|
|
24653
24817
|
const upload = buildStandardUpload(opts.base, readVerityIgnoreRaw());
|
|
24654
24818
|
const res = await apiRequest({
|
|
24655
24819
|
method: "POST",
|
|
24656
24820
|
path: "/standards/generate",
|
|
24657
24821
|
serviceUrl: opts.serviceUrl,
|
|
24658
24822
|
token: opts.token,
|
|
24659
|
-
body: { profile: opts.profile, base: upload.content, ...opts.replaces ? { replaces: opts.replaces } : {} },
|
|
24823
|
+
body: { profile: opts.profile, base: upload.content, ...opts.replaces !== void 0 ? { replaces: opts.replaces } : {} },
|
|
24660
24824
|
verbose: opts.verbose,
|
|
24661
24825
|
timeout: GENERATE_TIMEOUT_MS,
|
|
24662
24826
|
cmd: "standard_generate"
|
|
@@ -24664,12 +24828,17 @@ async function generateStandard(opts) {
|
|
|
24664
24828
|
if (!res.ok) {
|
|
24665
24829
|
if (res.http_status === 409 && res.error.startsWith("STANDARD_EXISTS")) return { status: "exists" };
|
|
24666
24830
|
if (res.http_status === 403 && res.error.startsWith("FEATURE_DISABLED")) return { status: "disabled" };
|
|
24831
|
+
if (res.http_status === 404 && /Unknown route/.test(res.error)) return { status: "unsupported" };
|
|
24667
24832
|
return { status: "failed", reason: terminalText(res.error, 300) };
|
|
24668
24833
|
}
|
|
24669
24834
|
const { version, content } = res.data;
|
|
24670
|
-
if (typeof version !== "number" || !content || typeof content !== "object") {
|
|
24835
|
+
if (typeof version !== "number" || !Number.isSafeInteger(version) || version < 1 || !content || typeof content !== "object" || Array.isArray(content)) {
|
|
24671
24836
|
return { status: "failed", reason: "the service answered without a Standard" };
|
|
24672
24837
|
}
|
|
24838
|
+
const valid = validateStandardContent(content);
|
|
24839
|
+
if (!valid.ok) {
|
|
24840
|
+
return { status: "failed", reason: `the service answered with a Standard this machine will not write (${terminalText(valid.error, 200)})` };
|
|
24841
|
+
}
|
|
24673
24842
|
const before = new Set(
|
|
24674
24843
|
(Array.isArray(opts.base.custom_patterns) ? opts.base.custom_patterns : []).map((p) => String(p.id))
|
|
24675
24844
|
);
|
|
@@ -24932,6 +25101,10 @@ async function runGenerate(globals, opts) {
|
|
|
24932
25101
|
spinner.warn("Rule generation is not switched on for this project yet. The built-in rules apply.");
|
|
24933
25102
|
return;
|
|
24934
25103
|
}
|
|
25104
|
+
if (outcome.status === "unsupported") {
|
|
25105
|
+
spinner.warn("This Verity service does not write project rules yet: it is older than this CLI. The built-in rules apply.");
|
|
25106
|
+
return;
|
|
25107
|
+
}
|
|
24935
25108
|
spinner.warn(`The rules could not be written: ${outcome.reason}`);
|
|
24936
25109
|
process.exit(1);
|
|
24937
25110
|
}
|
|
@@ -28071,7 +28244,7 @@ function channelSilence(input) {
|
|
|
28071
28244
|
// src/lib/cli-version.ts
|
|
28072
28245
|
function cliVersion() {
|
|
28073
28246
|
try {
|
|
28074
|
-
return true ? "0.35.0-experimental.
|
|
28247
|
+
return true ? "0.35.0-experimental.ce90a7b" : "dev";
|
|
28075
28248
|
} catch {
|
|
28076
28249
|
return "dev";
|
|
28077
28250
|
}
|
|
@@ -34671,7 +34844,7 @@ var LIMITS2 = {
|
|
|
34671
34844
|
abstracts: 32,
|
|
34672
34845
|
int: 1e9
|
|
34673
34846
|
};
|
|
34674
|
-
function
|
|
34847
|
+
function isPlainObject2(v) {
|
|
34675
34848
|
return typeof v === "object" && v !== null && !Array.isArray(v) && Object.getPrototypeOf(v) === Object.prototype;
|
|
34676
34849
|
}
|
|
34677
34850
|
function str2(v, max) {
|
|
@@ -34703,7 +34876,7 @@ function parseHeader(obj) {
|
|
|
34703
34876
|
if (!model || !Array.isArray(obj.abstracts) || obj.abstracts.length > LIMITS2.abstracts) return null;
|
|
34704
34877
|
const abstracts = [];
|
|
34705
34878
|
for (const a of obj.abstracts) {
|
|
34706
|
-
if (!
|
|
34879
|
+
if (!isPlainObject2(a)) return null;
|
|
34707
34880
|
const file = repoPath2(a.file);
|
|
34708
34881
|
const symbol = str2(a.symbol, LIMITS2.symbol);
|
|
34709
34882
|
const sha = a.sha256 === void 0 ? "" : str2(a.sha256, 80);
|
|
@@ -34775,7 +34948,7 @@ function parseVerityLines(stdout) {
|
|
|
34775
34948
|
out2.malformed++;
|
|
34776
34949
|
continue;
|
|
34777
34950
|
}
|
|
34778
|
-
if (!
|
|
34951
|
+
if (!isPlainObject2(obj)) {
|
|
34779
34952
|
out2.malformed++;
|
|
34780
34953
|
continue;
|
|
34781
34954
|
}
|
|
@@ -41560,7 +41733,7 @@ async function generate(ui, globals, profile, replaces) {
|
|
|
41560
41733
|
const reverts = profile.history.commits.filter((c) => /^revert\b/i.test(c.subject)).length;
|
|
41561
41734
|
rail.active("Writing review rules");
|
|
41562
41735
|
await rail.counted(([c, f, r]) => `${s.green}\u2713${s.reset} Read ${c} commits ${s.gray}\xB7${s.reset} ${f} fixes ${s.gray}\xB7${s.reset} ${r} reverts`, [commits, fixes, reverts]);
|
|
41563
|
-
if (profile.docs.length) rail.ticked(`Read ${profile.docs.map((d) => d.name).join(" and ")}`);
|
|
41736
|
+
if (profile.docs.length) rail.ticked(`Read ${profile.docs.map((d) => terminalText(d.name, 120)).join(" and ")}`);
|
|
41564
41737
|
if (ui.term.screen && !ui.term.motion) rail.line("Writing rules for this repository\u2026");
|
|
41565
41738
|
const started = Date.now();
|
|
41566
41739
|
const base = buildStandard({ detected: detectProject() }, loadCatalog());
|
|
@@ -41580,9 +41753,14 @@ async function generate(ui, globals, profile, replaces) {
|
|
|
41580
41753
|
rail.gap();
|
|
41581
41754
|
return { status: "fallback" };
|
|
41582
41755
|
}
|
|
41756
|
+
if (outcome.status === "unsupported") {
|
|
41757
|
+
rail.line(`This Verity service (${terminalText(url.data, 200)}) does not write project rules yet: it is older than this CLI. The built-in rules apply.`);
|
|
41758
|
+
rail.gap();
|
|
41759
|
+
return { status: "fallback" };
|
|
41760
|
+
}
|
|
41583
41761
|
if (outcome.status === "failed") {
|
|
41584
41762
|
rail.warn("The rules could not be written this time");
|
|
41585
|
-
rail.line(outcome.reason);
|
|
41763
|
+
rail.line(terminalText(outcome.reason, 300));
|
|
41586
41764
|
rail.line("The built-in rules apply. Try again later: verity standard generate");
|
|
41587
41765
|
rail.gap();
|
|
41588
41766
|
return { status: "fallback" };
|
|
@@ -41602,7 +41780,7 @@ async function generate(ui, globals, profile, replaces) {
|
|
|
41602
41780
|
rail.gap();
|
|
41603
41781
|
rail.done(`Standard v${outcome.version} saved`);
|
|
41604
41782
|
rail.line(`Your team gets the same rules. Edit them in ${STANDARD_FILE}`);
|
|
41605
|
-
if (outcome.warning) rail.line(outcome.warning, "warn");
|
|
41783
|
+
if (outcome.warning) rail.line(terminalText(outcome.warning, 600), "warn");
|
|
41606
41784
|
return { status: "created", version: outcome.version };
|
|
41607
41785
|
}
|
|
41608
41786
|
|
|
@@ -41915,7 +42093,7 @@ async function runInit(program2, opts) {
|
|
|
41915
42093
|
// The effective answer: the next run starts from this record.
|
|
41916
42094
|
moments: plan.momentIds,
|
|
41917
42095
|
...telemetry ? { telemetry } : {},
|
|
41918
|
-
init: { completed_at: (/* @__PURE__ */ new Date()).toISOString(), cli_version: true ? "0.35.0-experimental.
|
|
42096
|
+
init: { completed_at: (/* @__PURE__ */ new Date()).toISOString(), cli_version: true ? "0.35.0-experimental.ce90a7b" : "dev" }
|
|
41919
42097
|
});
|
|
41920
42098
|
} catch (err2) {
|
|
41921
42099
|
rail.line(`Could not record the setup answers: ${terminalText(err2.message, 200)}`, "warn");
|
|
@@ -42752,7 +42930,7 @@ function registerMemoryCommand(program2) {
|
|
|
42752
42930
|
memory2.command("pull").description("Download this repo's knowledge graph into .verity/memory/ (the session-start hook runs it)").option("--force", "Fetch every node even if nothing changed since the last pull").option("--quiet", "Print nothing and always exit 0 (for the session-start hook)").action(async (opts) => {
|
|
42753
42931
|
const globals = program2.opts();
|
|
42754
42932
|
const quiet = !!opts.quiet;
|
|
42755
|
-
const
|
|
42933
|
+
const fail2 = (message) => {
|
|
42756
42934
|
if (!quiet) printError(message);
|
|
42757
42935
|
process.exit(quiet ? 0 : 1);
|
|
42758
42936
|
};
|
|
@@ -42761,9 +42939,9 @@ function registerMemoryCommand(program2) {
|
|
|
42761
42939
|
} catch {
|
|
42762
42940
|
}
|
|
42763
42941
|
const tokenResult = await resolveToken(globals.token);
|
|
42764
|
-
if (!tokenResult.ok) return
|
|
42942
|
+
if (!tokenResult.ok) return fail2(tokenResult.error);
|
|
42765
42943
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
42766
|
-
if (!urlResult.ok) return
|
|
42944
|
+
if (!urlResult.ok) return fail2(urlResult.error);
|
|
42767
42945
|
let result;
|
|
42768
42946
|
try {
|
|
42769
42947
|
result = await pullRepoMemory({
|
|
@@ -42773,10 +42951,10 @@ function registerMemoryCommand(program2) {
|
|
|
42773
42951
|
force: !!opts.force
|
|
42774
42952
|
});
|
|
42775
42953
|
} catch (err2) {
|
|
42776
|
-
return
|
|
42954
|
+
return fail2(`Could not pull the knowledge graph: ${err2.message}`);
|
|
42777
42955
|
}
|
|
42778
42956
|
logEvent("memory_pull", result.ok ? { status: result.status, received: result.received, written: result.written } : { status: "failed", category: result.category ?? null });
|
|
42779
|
-
if (!result.ok) return
|
|
42957
|
+
if (!result.ok) return fail2(`Could not pull the knowledge graph: ${result.error}`);
|
|
42780
42958
|
if (!quiet) {
|
|
42781
42959
|
printInfo(result.status === "unchanged" ? "Knowledge graph is up to date." : result.status === "tracked" ? "Skipped: .verity/memory/ is tracked by git here, and the pull never rewrites tracked files. Run `verity memory untrack` to make the graph machine-local." : `Pulled ${result.received} node(s); ${result.written} new or updated file(s) written to .verity/memory/.`);
|
|
42782
42960
|
}
|
|
@@ -43745,8 +43923,8 @@ function registerLeanCommand(program2) {
|
|
|
43745
43923
|
}
|
|
43746
43924
|
|
|
43747
43925
|
// src/cli.ts
|
|
43748
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.35.0-experimental.
|
|
43749
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.35.0-experimental.
|
|
43926
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.35.0-experimental.ce90a7b").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
|
|
43927
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.35.0-experimental.ce90a7b");
|
|
43750
43928
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
43751
43929
|
try {
|
|
43752
43930
|
await foldLegacyLocalCredential();
|
package/package.json
CHANGED