@codacy/verity-cli 0.32.1-experimental.f2cf829 → 0.32.2-experimental.8843567
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/CHANGELOG.md +39 -2
- package/bin/verity.js +116 -39
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,7 +10,7 @@ All notable changes to Verity are documented here. This project follows
|
|
|
10
10
|
into its own heading when it is ready to be announced. -->
|
|
11
11
|
|
|
12
12
|
**Verity ships as a Claude Code plugin.** `/plugin marketplace add codacy/verity`
|
|
13
|
-
then `/plugin install verity@
|
|
13
|
+
then `/plugin install verity@verity` gives a working gate with nothing else to
|
|
14
14
|
install — the plugin carries the CLI as a pinned dependency, and Claude Code
|
|
15
15
|
installs and updates it for you.
|
|
16
16
|
|
|
@@ -47,7 +47,10 @@ installs are untouched.
|
|
|
47
47
|
- **A repository can no longer switch the gate off by shipping a file.**
|
|
48
48
|
Ownership was claimed by `.verity/.plugin-active`, a file inside the project,
|
|
49
49
|
and one naming any directory that happened to exist disabled every hook there.
|
|
50
|
-
An install Claude Code cannot vouch for is ignored
|
|
50
|
+
An install Claude Code cannot vouch for is ignored — and "vouch" now means
|
|
51
|
+
*for this checkout*: the cache path a real install lives at is predictable, so
|
|
52
|
+
a marker naming a plugin installed for **somebody else's project** used to be
|
|
53
|
+
believed here.
|
|
51
54
|
- **A plugin installed from a local marketplace directory is recognised.**
|
|
52
55
|
Claude Code runs a marketplace served from a directory out of that directory
|
|
53
56
|
while recording the cache copy it made, so the two paths disagreed and a live,
|
|
@@ -61,6 +64,40 @@ installs are untouched.
|
|
|
61
64
|
which is the ordinary case for someone whose first Verity install *is* the
|
|
62
65
|
plugin.
|
|
63
66
|
|
|
67
|
+
## [0.32.2] — 2026-09-10
|
|
68
|
+
|
|
69
|
+
**A patch for one bug, which stopped people before Verity was installed at all.**
|
|
70
|
+
|
|
71
|
+
### 🔌 The plugin marketplace is named `verity`
|
|
72
|
+
|
|
73
|
+
`/plugin install verity@codacy` is now **`/plugin install verity@verity`**. The
|
|
74
|
+
`marketplace add` line is unchanged — `codacy/verity` is the repository, not the
|
|
75
|
+
name.
|
|
76
|
+
|
|
77
|
+
Marketplace names are a flat, global namespace on your machine: no per-org
|
|
78
|
+
scoping, so two repositories that declare the same `name` compete for one slot.
|
|
79
|
+
Verity published as `codacy`, which `codacy/codacy-skills` already had — so
|
|
80
|
+
anyone who used that marketplace got
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Cannot add marketplace "codacy": its network source differs from the one
|
|
84
|
+
declared for it in settings …
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
and could never install Verity. The error names neither the file nor the fix.
|
|
88
|
+
|
|
89
|
+
**If you installed before this release**, the old plugin still runs but will
|
|
90
|
+
never update again:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
/plugin uninstall verity@codacy
|
|
94
|
+
/plugin marketplace add codacy/verity
|
|
95
|
+
/plugin install verity@verity
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`verity doctor` now detects both cases — a taken marketplace name, and a plugin
|
|
99
|
+
installed from the old one — and prints the file to edit and the commands to
|
|
100
|
+
run, so the next collision is a diagnosis rather than a dead end.
|
|
64
101
|
|
|
65
102
|
## [0.32.1] — 2026-09-09
|
|
66
103
|
|
package/bin/verity.js
CHANGED
|
@@ -12917,6 +12917,52 @@ function marketplaceLocations() {
|
|
|
12917
12917
|
}
|
|
12918
12918
|
return out;
|
|
12919
12919
|
}
|
|
12920
|
+
var VERITY_MARKETPLACE = "verity";
|
|
12921
|
+
var VERITY_MARKETPLACE_REPO = "codacy/verity";
|
|
12922
|
+
function marketplaceConflict() {
|
|
12923
|
+
const wanted = VERITY_MARKETPLACE;
|
|
12924
|
+
for (const file of ["settings.json", "settings.local.json"]) {
|
|
12925
|
+
const path = (0, import_node_path7.join)(claudeConfigDir(), file);
|
|
12926
|
+
const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
|
|
12927
|
+
const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
|
|
12928
|
+
if (entry2 && typeof entry2 === "object") {
|
|
12929
|
+
const src = entry2.source;
|
|
12930
|
+
if (!pointsAtVerity(src)) {
|
|
12931
|
+
return { name: wanted, declaredAs: describeSource(src), settingsFile: path };
|
|
12932
|
+
}
|
|
12933
|
+
}
|
|
12934
|
+
}
|
|
12935
|
+
const known = readJsonFile((0, import_node_path7.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
12936
|
+
const entry = known?.[wanted];
|
|
12937
|
+
if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
|
|
12938
|
+
return { name: wanted, declaredAs: describeSource(entry.source) };
|
|
12939
|
+
}
|
|
12940
|
+
return null;
|
|
12941
|
+
}
|
|
12942
|
+
function pointsAtVerity(src) {
|
|
12943
|
+
if (!src || typeof src !== "object") return false;
|
|
12944
|
+
const repo = typeof src.repo === "string" ? src.repo : "";
|
|
12945
|
+
if (repo.toLowerCase() === VERITY_MARKETPLACE_REPO) return true;
|
|
12946
|
+
const url = typeof src.url === "string" ? src.url : "";
|
|
12947
|
+
return /github\.com[/:]codacy\/verity(\.git)?\/?$/i.test(url);
|
|
12948
|
+
}
|
|
12949
|
+
function describeSource(src) {
|
|
12950
|
+
if (!src || typeof src !== "object") return "an unrecognised source";
|
|
12951
|
+
const kind = typeof src.source === "string" ? src.source : "unknown";
|
|
12952
|
+
const target = typeof src.repo === "string" && src.repo || typeof src.url === "string" && src.url || typeof src.path === "string" && src.path || "";
|
|
12953
|
+
return target ? `${kind} \u2192 ${target}` : kind;
|
|
12954
|
+
}
|
|
12955
|
+
function legacyMarketplaceInstall() {
|
|
12956
|
+
const plugins = readJsonFile((0, import_node_path7.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
12957
|
+
if (!plugins || typeof plugins !== "object") return null;
|
|
12958
|
+
for (const key of Object.keys(plugins)) {
|
|
12959
|
+
const at = key.lastIndexOf("@");
|
|
12960
|
+
if (at <= 0) continue;
|
|
12961
|
+
if (key.slice(0, at) !== "verity") continue;
|
|
12962
|
+
if (key.slice(at + 1) !== VERITY_MARKETPLACE) return key;
|
|
12963
|
+
}
|
|
12964
|
+
return null;
|
|
12965
|
+
}
|
|
12920
12966
|
function realpathOr(p) {
|
|
12921
12967
|
try {
|
|
12922
12968
|
return import_node_fs6.realpathSync.native(p);
|
|
@@ -12927,18 +12973,27 @@ function realpathOr(p) {
|
|
|
12927
12973
|
function isWithin(want, dir) {
|
|
12928
12974
|
return want === dir || want.startsWith(dir + import_node_path7.sep);
|
|
12929
12975
|
}
|
|
12976
|
+
function entryAppliesHere(entry, here) {
|
|
12977
|
+
const e = entry;
|
|
12978
|
+
const scope2 = typeof e?.scope === "string" ? e.scope : "user";
|
|
12979
|
+
if (scope2 === "user") return true;
|
|
12980
|
+
const forProject = typeof e?.projectPath === "string" ? realpathOr(e.projectPath) : "";
|
|
12981
|
+
return forProject === here;
|
|
12982
|
+
}
|
|
12930
12983
|
function registrySays(pluginRoot) {
|
|
12931
12984
|
const plugins = readJsonFile((0, import_node_path7.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
12932
12985
|
if (!plugins || typeof plugins !== "object") return "unverified";
|
|
12933
12986
|
const want = (0, import_node_path7.resolve)(pluginRoot);
|
|
12987
|
+
const here = realpathOr(repoRoot());
|
|
12934
12988
|
const markets = marketplaceLocations();
|
|
12935
12989
|
for (const [key, value] of Object.entries(plugins)) {
|
|
12936
12990
|
const at = key.lastIndexOf("@");
|
|
12937
12991
|
const source = at > 0 ? markets.get(key.slice(at + 1)) : void 0;
|
|
12938
|
-
const
|
|
12992
|
+
const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
|
|
12993
|
+
const claims = applicable.some((entry) => {
|
|
12939
12994
|
const installPath = entry?.installPath;
|
|
12940
12995
|
return typeof installPath === "string" && (0, import_node_path7.resolve)(installPath) === want;
|
|
12941
|
-
}) || source !== void 0 && isWithin(want, source);
|
|
12996
|
+
}) || source !== void 0 && applicable.length > 0 && isWithin(want, source);
|
|
12942
12997
|
if (claims) {
|
|
12943
12998
|
if (enabledPluginSetting(key) === false) return "gone";
|
|
12944
12999
|
return (0, import_node_fs6.existsSync)(pluginRoot) ? "live" : "gone";
|
|
@@ -12998,11 +13053,7 @@ function registeredVerityPlugin() {
|
|
|
12998
13053
|
const e = entry;
|
|
12999
13054
|
const installPath = typeof e.installPath === "string" ? e.installPath : "";
|
|
13000
13055
|
if (!installPath || !(0, import_node_fs6.existsSync)(installPath)) continue;
|
|
13001
|
-
|
|
13002
|
-
if (scope2 !== "user") {
|
|
13003
|
-
const forProject = typeof e.projectPath === "string" ? realpathOr(e.projectPath) : "";
|
|
13004
|
-
if (forProject !== here) continue;
|
|
13005
|
-
}
|
|
13056
|
+
if (!entryAppliesHere(entry, here)) continue;
|
|
13006
13057
|
return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
|
|
13007
13058
|
}
|
|
13008
13059
|
}
|
|
@@ -20867,7 +20918,7 @@ function channelSilence(input) {
|
|
|
20867
20918
|
// src/lib/cli-version.ts
|
|
20868
20919
|
function cliVersion() {
|
|
20869
20920
|
try {
|
|
20870
|
-
return true ? "0.32.
|
|
20921
|
+
return true ? "0.32.2-experimental.8843567" : "dev";
|
|
20871
20922
|
} catch {
|
|
20872
20923
|
return "dev";
|
|
20873
20924
|
}
|
|
@@ -24615,36 +24666,50 @@ async function runGuard(opts, globals) {
|
|
|
24615
24666
|
process.exit(2);
|
|
24616
24667
|
}
|
|
24617
24668
|
resetIter(moment);
|
|
24669
|
+
const notice = verdictNotice({
|
|
24670
|
+
decision,
|
|
24671
|
+
moment,
|
|
24672
|
+
verb,
|
|
24673
|
+
covLine,
|
|
24674
|
+
covDetail,
|
|
24675
|
+
link,
|
|
24676
|
+
viewUrl,
|
|
24677
|
+
narrative: response.assessment?.narrative ?? ""
|
|
24678
|
+
});
|
|
24679
|
+
emitAllowNotice(notice.user, notice.agent);
|
|
24680
|
+
}
|
|
24681
|
+
function verdictNotice(ctx) {
|
|
24682
|
+
const { moment, verb, covLine, covDetail, link, viewUrl } = ctx;
|
|
24683
|
+
const decision = ctx.decision ?? "(unrecognised)";
|
|
24684
|
+
const report = viewUrl ? `
|
|
24685
|
+
Report: ${viewUrl}` : "";
|
|
24618
24686
|
if (decision === "FAIL") {
|
|
24619
|
-
const narrative =
|
|
24620
|
-
|
|
24621
|
-
`\u26A0 Verity ${moment}: the ${verb} may not match its stated purpose \u2014 proceeding (${covLine})${link}`,
|
|
24622
|
-
`Verity ${moment}: intent-alignment WARNING (not blocked).${narrative ? " " + narrative : ""}
|
|
24623
|
-
${covDetail}${
|
|
24624
|
-
|
|
24625
|
-
|
|
24626
|
-
|
|
24627
|
-
|
|
24628
|
-
`\u26A0 Verity ${moment}: WARN \u2014 proceeding (${covLine})${link}`,
|
|
24629
|
-
`Verity ${moment} review: WARN (proceeding).
|
|
24630
|
-
${covDetail}${
|
|
24631
|
-
|
|
24632
|
-
);
|
|
24633
|
-
} else if (decision === "PASS") {
|
|
24634
|
-
emitAllowNotice(
|
|
24635
|
-
`\u2713 Verity ${moment}: PASS (${covLine})${link}`,
|
|
24636
|
-
`Verity ${moment} review: PASS.
|
|
24637
|
-
${covDetail}${viewUrl ? `
|
|
24638
|
-
Report: ${viewUrl}` : ""}`
|
|
24639
|
-
);
|
|
24640
|
-
} else {
|
|
24641
|
-
emitAllowNotice(
|
|
24642
|
-
`\u26A0 Verity ${moment}: no verdict came back \u2014 ${verb === "commit" ? "committed" : "pushed"} WITHOUT a usable review (${covLine})${link}`,
|
|
24643
|
-
`Verity ${moment}: the service answered with no recognisable gate decision (${decision}); the ${verb} was allowed, but nothing reviewed it. Treat this as unreviewed, not as a pass.
|
|
24644
|
-
${covDetail}${viewUrl ? `
|
|
24645
|
-
Report: ${viewUrl}` : ""}`
|
|
24646
|
-
);
|
|
24687
|
+
const narrative = ctx.narrative ?? "";
|
|
24688
|
+
return {
|
|
24689
|
+
user: `\u26A0 Verity ${moment}: the ${verb} may not match its stated purpose \u2014 proceeding (${covLine})${link}`,
|
|
24690
|
+
agent: `Verity ${moment}: intent-alignment WARNING (not blocked).${narrative ? " " + narrative : ""}
|
|
24691
|
+
${covDetail}${report}`
|
|
24692
|
+
};
|
|
24693
|
+
}
|
|
24694
|
+
if (decision === "WARN") {
|
|
24695
|
+
return {
|
|
24696
|
+
user: `\u26A0 Verity ${moment}: WARN \u2014 proceeding (${covLine})${link}`,
|
|
24697
|
+
agent: `Verity ${moment} review: WARN (proceeding).
|
|
24698
|
+
${covDetail}${report}`
|
|
24699
|
+
};
|
|
24647
24700
|
}
|
|
24701
|
+
if (decision === "PASS") {
|
|
24702
|
+
return {
|
|
24703
|
+
user: `\u2713 Verity ${moment}: PASS (${covLine})${link}`,
|
|
24704
|
+
agent: `Verity ${moment} review: PASS.
|
|
24705
|
+
${covDetail}${report}`
|
|
24706
|
+
};
|
|
24707
|
+
}
|
|
24708
|
+
return {
|
|
24709
|
+
user: `\u26A0 Verity ${moment}: no verdict came back \u2014 ${verb === "commit" ? "committed" : "pushed"} WITHOUT a usable review (${covLine})${link}`,
|
|
24710
|
+
agent: `Verity ${moment}: the service answered with no recognisable gate decision (${decision}); the ${verb} was allowed, but nothing reviewed it. Treat this as unreviewed, not as a pass.
|
|
24711
|
+
${covDetail}${report}`
|
|
24712
|
+
};
|
|
24648
24713
|
}
|
|
24649
24714
|
function writeBlockMessage(moment, response, covDetail) {
|
|
24650
24715
|
const label2 = moment === "pre-commit" ? "pre-commit" : "pre-push";
|
|
@@ -25265,6 +25330,18 @@ async function buildReport() {
|
|
|
25265
25330
|
if (state?.telemetry === "deferred") {
|
|
25266
25331
|
next.push('Telemetry was requested but needs a token \u2014 run "verity login", then "verity telemetry install".');
|
|
25267
25332
|
}
|
|
25333
|
+
const conflict = marketplaceConflict();
|
|
25334
|
+
if (conflict) {
|
|
25335
|
+
next.push(
|
|
25336
|
+
`The marketplace name "${conflict.name}" is already taken on this machine by ${conflict.declaredAs}, so "/plugin marketplace add codacy/verity" will be refused. ` + (conflict.settingsFile ? `Remove the "${conflict.name}" entry from extraKnownMarketplaces in ${conflict.settingsFile} ` : `Run "/plugin marketplace remove ${conflict.name}" `) + "and restart Claude Code, then add it again."
|
|
25337
|
+
);
|
|
25338
|
+
}
|
|
25339
|
+
const legacy = legacyMarketplaceInstall();
|
|
25340
|
+
if (legacy) {
|
|
25341
|
+
next.push(
|
|
25342
|
+
`The Verity plugin is installed as "${legacy}", from a marketplace name Verity no longer publishes under \u2014 it still runs, but it will never see another update. Run "/plugin uninstall ${legacy}", then "/plugin marketplace add codacy/verity" and "/plugin install verity@verity".`
|
|
25343
|
+
);
|
|
25344
|
+
}
|
|
25268
25345
|
return {
|
|
25269
25346
|
prerequisites: prereqs.checks,
|
|
25270
25347
|
blocked: prereqs.blocked,
|
|
@@ -26667,7 +26744,7 @@ function registerInitCommand(program2) {
|
|
|
26667
26744
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
26668
26745
|
init: {
|
|
26669
26746
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26670
|
-
cli_version: true ? "0.32.
|
|
26747
|
+
cli_version: true ? "0.32.2-experimental.8843567" : "dev"
|
|
26671
26748
|
}
|
|
26672
26749
|
});
|
|
26673
26750
|
} catch (err) {
|
|
@@ -27347,8 +27424,8 @@ function registerTelemetryCommands(program2) {
|
|
|
27347
27424
|
}
|
|
27348
27425
|
|
|
27349
27426
|
// src/cli.ts
|
|
27350
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.32.
|
|
27351
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.
|
|
27427
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.32.2-experimental.8843567").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) => {
|
|
27428
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.2-experimental.8843567");
|
|
27352
27429
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
27353
27430
|
try {
|
|
27354
27431
|
await foldLegacyLocalCredential();
|
package/package.json
CHANGED