@codacy/verity-cli 0.33.0-experimental.d60f544 → 0.33.1-experimental.1378de3
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 +41 -0
- package/bin/verity.js +1024 -695
- package/package.json +2 -2
package/bin/verity.js
CHANGED
|
@@ -10413,6 +10413,7 @@ var MAX_ITERATIONS = 2;
|
|
|
10413
10413
|
var MAX_SPEC_FILES = 6;
|
|
10414
10414
|
var MAX_SPEC_FILE_BYTES = 512e3;
|
|
10415
10415
|
var MAX_TOTAL_SPEC_BYTES = 512e3;
|
|
10416
|
+
var MAX_EXPLICIT_SPEC_FILE_BYTES = 10240;
|
|
10416
10417
|
var MAX_PLAN_FILES = 3;
|
|
10417
10418
|
var MAX_PLAN_FILE_BYTES = 512e3;
|
|
10418
10419
|
var MAX_INTENT_CHARS = 2e3;
|
|
@@ -10969,8 +10970,8 @@ function filterReviewable(files) {
|
|
|
10969
10970
|
const ext = (0, import_node_path3.extname)(f).slice(1);
|
|
10970
10971
|
if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
|
|
10971
10972
|
if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
|
|
10972
|
-
const
|
|
10973
|
-
if (REVIEWABLE_FILENAMES.has(
|
|
10973
|
+
const basename5 = f.split("/").pop() ?? "";
|
|
10974
|
+
if (REVIEWABLE_FILENAMES.has(basename5)) return true;
|
|
10974
10975
|
if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
|
|
10975
10976
|
return false;
|
|
10976
10977
|
});
|
|
@@ -12800,12 +12801,50 @@ function resolveGuardMoments(explicit) {
|
|
|
12800
12801
|
}
|
|
12801
12802
|
|
|
12802
12803
|
// src/lib/plugin-ownership.ts
|
|
12803
|
-
var
|
|
12804
|
-
|
|
12804
|
+
var import_node_fs7 = require("node:fs");
|
|
12805
|
+
|
|
12806
|
+
// src/lib/which.ts
|
|
12807
|
+
var import_node_fs5 = require("node:fs");
|
|
12805
12808
|
var import_node_path7 = require("node:path");
|
|
12809
|
+
function executableExtensions(platform, pathext) {
|
|
12810
|
+
if (platform !== "win32") return [""];
|
|
12811
|
+
const raw = (pathext ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
|
|
12812
|
+
const out = [];
|
|
12813
|
+
for (const ext of raw) {
|
|
12814
|
+
const lower = ext.toLowerCase();
|
|
12815
|
+
if (!out.includes(lower)) out.push(lower);
|
|
12816
|
+
if (!out.includes(ext)) out.push(ext);
|
|
12817
|
+
}
|
|
12818
|
+
return out;
|
|
12819
|
+
}
|
|
12820
|
+
function whichSync(bin, opts = {}) {
|
|
12821
|
+
const platform = opts.platform ?? process.platform;
|
|
12822
|
+
const rawPath = opts.path ?? process.env.PATH ?? "";
|
|
12823
|
+
if (!rawPath) return null;
|
|
12824
|
+
const exts = executableExtensions(platform, opts.pathext ?? process.env.PATHEXT);
|
|
12825
|
+
const real = opts.real ?? true;
|
|
12826
|
+
for (const dir of rawPath.split(import_node_path7.delimiter)) {
|
|
12827
|
+
if (!dir) continue;
|
|
12828
|
+
for (const ext of exts) {
|
|
12829
|
+
const candidate = (0, import_node_path7.join)(dir, bin + ext);
|
|
12830
|
+
try {
|
|
12831
|
+
if (!(0, import_node_fs5.statSync)(candidate).isFile()) continue;
|
|
12832
|
+
if (platform !== "win32") (0, import_node_fs5.accessSync)(candidate, import_node_fs5.constants.X_OK);
|
|
12833
|
+
return real ? (0, import_node_fs5.realpathSync)(candidate) : candidate;
|
|
12834
|
+
} catch {
|
|
12835
|
+
continue;
|
|
12836
|
+
}
|
|
12837
|
+
}
|
|
12838
|
+
}
|
|
12839
|
+
return null;
|
|
12840
|
+
}
|
|
12841
|
+
|
|
12842
|
+
// src/lib/plugin-ownership.ts
|
|
12843
|
+
var import_node_os2 = require("node:os");
|
|
12844
|
+
var import_node_path8 = require("node:path");
|
|
12806
12845
|
|
|
12807
12846
|
// src/lib/stderr-log.ts
|
|
12808
|
-
var
|
|
12847
|
+
var import_node_fs6 = require("node:fs");
|
|
12809
12848
|
var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
|
|
12810
12849
|
var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
12811
12850
|
function scrub(s) {
|
|
@@ -12818,9 +12857,9 @@ function append(text) {
|
|
|
12818
12857
|
try {
|
|
12819
12858
|
const dir = projectPath(DEBUG_LOG_DIR);
|
|
12820
12859
|
const file = projectPath(STDERR_LOG_FILE);
|
|
12821
|
-
(0,
|
|
12860
|
+
(0, import_node_fs6.mkdirSync)(dir, { recursive: true });
|
|
12822
12861
|
rotateIfNeeded(file);
|
|
12823
|
-
(0,
|
|
12862
|
+
(0, import_node_fs6.appendFileSync)(file, text);
|
|
12824
12863
|
} catch {
|
|
12825
12864
|
}
|
|
12826
12865
|
}
|
|
@@ -12868,14 +12907,15 @@ function markerPath() {
|
|
|
12868
12907
|
}
|
|
12869
12908
|
function readMarker() {
|
|
12870
12909
|
try {
|
|
12871
|
-
if (!(0,
|
|
12872
|
-
const raw = JSON.parse((0,
|
|
12910
|
+
if (!(0, import_node_fs7.existsSync)(markerPath())) return null;
|
|
12911
|
+
const raw = JSON.parse((0, import_node_fs7.readFileSync)(markerPath(), "utf-8"));
|
|
12873
12912
|
const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
|
|
12874
12913
|
if (!pluginRoot || CONTROL_CHARS.test(pluginRoot)) return null;
|
|
12914
|
+
const version = typeof raw.version === "string" && !CONTROL_CHARS.test(raw.version) ? raw.version : null;
|
|
12875
12915
|
return {
|
|
12876
12916
|
session_id: typeof raw.session_id === "string" ? raw.session_id : null,
|
|
12877
12917
|
plugin_root: pluginRoot,
|
|
12878
|
-
version
|
|
12918
|
+
version,
|
|
12879
12919
|
ts: typeof raw.ts === "number" ? raw.ts : 0
|
|
12880
12920
|
};
|
|
12881
12921
|
} catch {
|
|
@@ -12886,23 +12926,23 @@ function recordPluginOwnership(sessionId) {
|
|
|
12886
12926
|
const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
|
|
12887
12927
|
if (!pluginRoot) return;
|
|
12888
12928
|
try {
|
|
12889
|
-
(0,
|
|
12929
|
+
(0, import_node_fs7.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
12890
12930
|
const marker = {
|
|
12891
12931
|
session_id: sessionId,
|
|
12892
12932
|
plugin_root: pluginRoot,
|
|
12893
12933
|
version: process.env.VERITY_PLUGIN_VERSION || null,
|
|
12894
12934
|
ts: Math.floor(Date.now() / 1e3)
|
|
12895
12935
|
};
|
|
12896
|
-
(0,
|
|
12936
|
+
(0, import_node_fs7.writeFileSync)(markerPath(), JSON.stringify(marker));
|
|
12897
12937
|
} catch {
|
|
12898
12938
|
}
|
|
12899
12939
|
}
|
|
12900
12940
|
function claudeConfigDir() {
|
|
12901
|
-
return process.env.CLAUDE_CONFIG_DIR || (0,
|
|
12941
|
+
return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path8.join)((0, import_node_os2.homedir)(), ".claude");
|
|
12902
12942
|
}
|
|
12903
12943
|
function readJsonFile(path) {
|
|
12904
12944
|
try {
|
|
12905
|
-
const parsed = JSON.parse((0,
|
|
12945
|
+
const parsed = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf-8"));
|
|
12906
12946
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
12907
12947
|
} catch {
|
|
12908
12948
|
return null;
|
|
@@ -12910,9 +12950,9 @@ function readJsonFile(path) {
|
|
|
12910
12950
|
}
|
|
12911
12951
|
function enabledPluginSetting(key) {
|
|
12912
12952
|
const files = [
|
|
12913
|
-
projectPath((0,
|
|
12914
|
-
projectPath((0,
|
|
12915
|
-
(0,
|
|
12953
|
+
projectPath((0, import_node_path8.join)(".claude", "settings.local.json")),
|
|
12954
|
+
projectPath((0, import_node_path8.join)(".claude", "settings.json")),
|
|
12955
|
+
(0, import_node_path8.join)(claudeConfigDir(), "settings.json")
|
|
12916
12956
|
];
|
|
12917
12957
|
for (const file of files) {
|
|
12918
12958
|
const map = readJsonFile(file)?.enabledPlugins;
|
|
@@ -12924,27 +12964,16 @@ function enabledPluginSetting(key) {
|
|
|
12924
12964
|
}
|
|
12925
12965
|
function marketplaceLocations() {
|
|
12926
12966
|
const out = /* @__PURE__ */ new Map();
|
|
12927
|
-
const known = readJsonFile((0,
|
|
12967
|
+
const known = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
12928
12968
|
if (!known) return out;
|
|
12929
12969
|
for (const [name, entry] of Object.entries(known)) {
|
|
12930
12970
|
const loc2 = entry?.installLocation;
|
|
12931
|
-
if (typeof loc2 === "string" && loc2) out.set(name, (0,
|
|
12971
|
+
if (typeof loc2 === "string" && loc2) out.set(name, (0, import_node_path8.resolve)(loc2));
|
|
12932
12972
|
}
|
|
12933
12973
|
return out;
|
|
12934
12974
|
}
|
|
12935
12975
|
function verityPathEntry() {
|
|
12936
|
-
|
|
12937
|
-
if (!path) return null;
|
|
12938
|
-
for (const dir of path.split(import_node_path7.delimiter)) {
|
|
12939
|
-
if (!dir) continue;
|
|
12940
|
-
const candidate = (0, import_node_path7.join)(dir, "verity");
|
|
12941
|
-
try {
|
|
12942
|
-
(0, import_node_fs6.accessSync)(candidate, import_node_fs6.constants.X_OK);
|
|
12943
|
-
return candidate;
|
|
12944
|
-
} catch {
|
|
12945
|
-
}
|
|
12946
|
-
}
|
|
12947
|
-
return null;
|
|
12976
|
+
return whichSync("verity", { real: false });
|
|
12948
12977
|
}
|
|
12949
12978
|
function verityOnPath() {
|
|
12950
12979
|
return verityPathEntry() !== null;
|
|
@@ -12953,27 +12982,13 @@ function globalVerityVersion() {
|
|
|
12953
12982
|
const entry = verityPathEntry();
|
|
12954
12983
|
if (!entry) return null;
|
|
12955
12984
|
try {
|
|
12956
|
-
const pkg = readJsonFile((0,
|
|
12985
|
+
const pkg = readJsonFile((0, import_node_path8.join)((0, import_node_path8.dirname)((0, import_node_fs7.realpathSync)(entry)), "..", "package.json"));
|
|
12957
12986
|
if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
|
|
12958
12987
|
return pkg.version;
|
|
12959
12988
|
} catch {
|
|
12960
12989
|
return null;
|
|
12961
12990
|
}
|
|
12962
12991
|
}
|
|
12963
|
-
function pluginCliInvocation() {
|
|
12964
|
-
const root = process.env.VERITY_PLUGIN_ROOT;
|
|
12965
|
-
if (!root) return null;
|
|
12966
|
-
const onPath = globalVerityVersion();
|
|
12967
|
-
if (onPath !== null && onPath === activePluginVersion()) return null;
|
|
12968
|
-
return `node ${JSON.stringify((0, import_node_path7.join)(root, "scripts", "verity.mjs"))}`;
|
|
12969
|
-
}
|
|
12970
|
-
function cliVersionSkew() {
|
|
12971
|
-
if (!process.env.VERITY_PLUGIN_ROOT) return null;
|
|
12972
|
-
const onPath = globalVerityVersion();
|
|
12973
|
-
const plugin = activePluginVersion();
|
|
12974
|
-
if (!onPath || !plugin || onPath === plugin) return null;
|
|
12975
|
-
return { global: onPath, plugin };
|
|
12976
|
-
}
|
|
12977
12992
|
function activePluginVersion() {
|
|
12978
12993
|
const fromEnv = process.env.VERITY_PLUGIN_VERSION;
|
|
12979
12994
|
if (fromEnv) return fromEnv;
|
|
@@ -12984,7 +12999,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
|
|
|
12984
12999
|
function marketplaceConflict() {
|
|
12985
13000
|
const wanted = VERITY_MARKETPLACE;
|
|
12986
13001
|
for (const file of ["settings.json", "settings.local.json"]) {
|
|
12987
|
-
const path = (0,
|
|
13002
|
+
const path = (0, import_node_path8.join)(claudeConfigDir(), file);
|
|
12988
13003
|
const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
|
|
12989
13004
|
const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
|
|
12990
13005
|
if (entry2 && typeof entry2 === "object") {
|
|
@@ -12994,7 +13009,7 @@ function marketplaceConflict() {
|
|
|
12994
13009
|
}
|
|
12995
13010
|
}
|
|
12996
13011
|
}
|
|
12997
|
-
const known = readJsonFile((0,
|
|
13012
|
+
const known = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
12998
13013
|
const entry = known?.[wanted];
|
|
12999
13014
|
if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
|
|
13000
13015
|
return { name: wanted, declaredAs: describeSource(entry.source) };
|
|
@@ -13015,7 +13030,7 @@ function describeSource(src) {
|
|
|
13015
13030
|
return target ? `${kind} \u2192 ${target}` : kind;
|
|
13016
13031
|
}
|
|
13017
13032
|
function legacyMarketplaceInstall() {
|
|
13018
|
-
const plugins = readJsonFile((0,
|
|
13033
|
+
const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
13019
13034
|
if (!plugins || typeof plugins !== "object") return null;
|
|
13020
13035
|
for (const key of Object.keys(plugins)) {
|
|
13021
13036
|
const at = key.lastIndexOf("@");
|
|
@@ -13027,13 +13042,13 @@ function legacyMarketplaceInstall() {
|
|
|
13027
13042
|
}
|
|
13028
13043
|
function realpathOr(p) {
|
|
13029
13044
|
try {
|
|
13030
|
-
return
|
|
13045
|
+
return import_node_fs7.realpathSync.native(p);
|
|
13031
13046
|
} catch {
|
|
13032
|
-
return (0,
|
|
13047
|
+
return (0, import_node_path8.resolve)(p);
|
|
13033
13048
|
}
|
|
13034
13049
|
}
|
|
13035
13050
|
function isWithin(want, dir) {
|
|
13036
|
-
return want === dir || want.startsWith(dir +
|
|
13051
|
+
return want === dir || want.startsWith(dir + import_node_path8.sep);
|
|
13037
13052
|
}
|
|
13038
13053
|
function entryAppliesHere(entry, here) {
|
|
13039
13054
|
const e = entry;
|
|
@@ -13043,9 +13058,9 @@ function entryAppliesHere(entry, here) {
|
|
|
13043
13058
|
return forProject === here;
|
|
13044
13059
|
}
|
|
13045
13060
|
function registrySays(pluginRoot) {
|
|
13046
|
-
const plugins = readJsonFile((0,
|
|
13061
|
+
const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
13047
13062
|
if (!plugins || typeof plugins !== "object") return "unverified";
|
|
13048
|
-
const want = (0,
|
|
13063
|
+
const want = (0, import_node_path8.resolve)(pluginRoot);
|
|
13049
13064
|
const here = realpathOr(repoRoot());
|
|
13050
13065
|
const markets = marketplaceLocations();
|
|
13051
13066
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -13054,15 +13069,15 @@ function registrySays(pluginRoot) {
|
|
|
13054
13069
|
const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
|
|
13055
13070
|
const claims = applicable.some((entry) => {
|
|
13056
13071
|
const installPath = entry?.installPath;
|
|
13057
|
-
return typeof installPath === "string" && (0,
|
|
13072
|
+
return typeof installPath === "string" && (0, import_node_path8.resolve)(installPath) === want;
|
|
13058
13073
|
}) || source !== void 0 && applicable.length > 0 && isWithin(want, source);
|
|
13059
13074
|
if (claims) {
|
|
13060
13075
|
if (enabledPluginSetting(key) === false) return "gone";
|
|
13061
|
-
return (0,
|
|
13076
|
+
return (0, import_node_fs7.existsSync)(pluginRoot) ? "live" : "gone";
|
|
13062
13077
|
}
|
|
13063
13078
|
}
|
|
13064
|
-
const managed = (0,
|
|
13065
|
-
return want === managed || want.startsWith(managed +
|
|
13079
|
+
const managed = (0, import_node_path8.resolve)((0, import_node_path8.join)(claudeConfigDir(), "plugins", "cache"));
|
|
13080
|
+
return want === managed || want.startsWith(managed + import_node_path8.sep) ? "gone" : "unverified";
|
|
13066
13081
|
}
|
|
13067
13082
|
var _live = /* @__PURE__ */ new Map();
|
|
13068
13083
|
function pluginLiveness(pluginRoot) {
|
|
@@ -13076,7 +13091,7 @@ function clearStalePluginMarker() {
|
|
|
13076
13091
|
const marker = readMarker();
|
|
13077
13092
|
if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
|
|
13078
13093
|
try {
|
|
13079
|
-
(0,
|
|
13094
|
+
(0, import_node_fs7.rmSync)(markerPath(), { force: true });
|
|
13080
13095
|
} catch {
|
|
13081
13096
|
return null;
|
|
13082
13097
|
}
|
|
@@ -13104,7 +13119,7 @@ function pluginActiveHere() {
|
|
|
13104
13119
|
return activePluginInstall() !== null;
|
|
13105
13120
|
}
|
|
13106
13121
|
function registeredVerityPlugin() {
|
|
13107
|
-
const plugins = readJsonFile((0,
|
|
13122
|
+
const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
13108
13123
|
if (!plugins || typeof plugins !== "object") return null;
|
|
13109
13124
|
const here = realpathOr(repoRoot());
|
|
13110
13125
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -13114,7 +13129,7 @@ function registeredVerityPlugin() {
|
|
|
13114
13129
|
for (const entry of Array.isArray(value) ? value : []) {
|
|
13115
13130
|
const e = entry;
|
|
13116
13131
|
const installPath = typeof e.installPath === "string" ? e.installPath : "";
|
|
13117
|
-
if (!installPath || !(0,
|
|
13132
|
+
if (!installPath || !(0, import_node_fs7.existsSync)(installPath)) continue;
|
|
13118
13133
|
if (!entryAppliesHere(entry, here)) continue;
|
|
13119
13134
|
return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
|
|
13120
13135
|
}
|
|
@@ -13165,6 +13180,150 @@ async function resolveHookWiring() {
|
|
|
13165
13180
|
};
|
|
13166
13181
|
}
|
|
13167
13182
|
|
|
13183
|
+
// src/lib/cli-provenance.ts
|
|
13184
|
+
var import_node_fs8 = require("node:fs");
|
|
13185
|
+
var import_node_os3 = require("node:os");
|
|
13186
|
+
var import_node_path9 = require("node:path");
|
|
13187
|
+
var CLI_PACKAGE = "@codacy/verity-cli";
|
|
13188
|
+
var CLI_ENTRY = (0, import_node_path9.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
|
|
13189
|
+
function readJson(path) {
|
|
13190
|
+
try {
|
|
13191
|
+
const parsed = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf-8"));
|
|
13192
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
13193
|
+
} catch {
|
|
13194
|
+
return null;
|
|
13195
|
+
}
|
|
13196
|
+
}
|
|
13197
|
+
function versionUnder(base) {
|
|
13198
|
+
const entry = (0, import_node_path9.join)(base, CLI_ENTRY);
|
|
13199
|
+
if (!(0, import_node_fs8.existsSync)(entry)) return null;
|
|
13200
|
+
const pkg = readJson((0, import_node_path9.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
|
|
13201
|
+
return typeof pkg?.version === "string" ? pkg.version : null;
|
|
13202
|
+
}
|
|
13203
|
+
function versionForEntry(entry) {
|
|
13204
|
+
try {
|
|
13205
|
+
const pkg = readJson((0, import_node_path9.join)((0, import_node_path9.dirname)((0, import_node_fs8.realpathSync)(entry)), "..", "package.json"));
|
|
13206
|
+
return typeof pkg?.version === "string" ? pkg.version : null;
|
|
13207
|
+
} catch {
|
|
13208
|
+
return null;
|
|
13209
|
+
}
|
|
13210
|
+
}
|
|
13211
|
+
function resolveHooksCli(pluginRoot) {
|
|
13212
|
+
const override = process.env.VERITY_CLI_PATH;
|
|
13213
|
+
if (override && (0, import_node_fs8.existsSync)(override)) {
|
|
13214
|
+
return { version: versionForEntry(override), rung: "override" };
|
|
13215
|
+
}
|
|
13216
|
+
const fromPlugin = versionUnder(pluginRoot);
|
|
13217
|
+
if (fromPlugin !== null) return { version: fromPlugin, rung: "plugin" };
|
|
13218
|
+
if ((0, import_node_fs8.existsSync)((0, import_node_path9.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
|
|
13219
|
+
const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path9.join)((0, import_node_os3.homedir)(), ".verity", "plugin-cli");
|
|
13220
|
+
const fromData = versionUnder(dataDir);
|
|
13221
|
+
if (fromData !== null) return { version: fromData, rung: "plugin-data" };
|
|
13222
|
+
if ((0, import_node_fs8.existsSync)((0, import_node_path9.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
|
|
13223
|
+
const global = globalVerityVersion();
|
|
13224
|
+
if (global !== null) return { version: global, rung: "global" };
|
|
13225
|
+
return null;
|
|
13226
|
+
}
|
|
13227
|
+
function compareVersions(a, b) {
|
|
13228
|
+
const parse = (v) => {
|
|
13229
|
+
const [core, ...rest] = v.split("-");
|
|
13230
|
+
const parts = core.split(".");
|
|
13231
|
+
if (parts.length !== 3) return null;
|
|
13232
|
+
const nums = parts.map((p) => /^\d+$/.test(p) ? Number(p) : NaN);
|
|
13233
|
+
if (nums.some(Number.isNaN)) return null;
|
|
13234
|
+
return { nums, pre: rest.join("-") };
|
|
13235
|
+
};
|
|
13236
|
+
const x = parse(a);
|
|
13237
|
+
const y = parse(b);
|
|
13238
|
+
if (!x || !y) return null;
|
|
13239
|
+
for (let i = 0; i < 3; i++) {
|
|
13240
|
+
if (x.nums[i] !== y.nums[i]) return x.nums[i] < y.nums[i] ? -1 : 1;
|
|
13241
|
+
}
|
|
13242
|
+
if (x.pre === y.pre) return 0;
|
|
13243
|
+
if (!x.pre) return 1;
|
|
13244
|
+
if (!y.pre) return -1;
|
|
13245
|
+
return null;
|
|
13246
|
+
}
|
|
13247
|
+
var PLUGIN_UPDATE_REMEDY = "claude plugin update verity@verity, then /reload-plugins (or restart Claude Code)";
|
|
13248
|
+
function globalUpdateRemedy(version) {
|
|
13249
|
+
return `npm install -g ${CLI_PACKAGE}@${version}`;
|
|
13250
|
+
}
|
|
13251
|
+
function remedyFor(global, hooks) {
|
|
13252
|
+
const order = compareVersions(global, hooks);
|
|
13253
|
+
if (order === -1) return { behind: "global", remedy: globalUpdateRemedy(hooks) };
|
|
13254
|
+
if (order === 1) return { behind: "plugin", remedy: PLUGIN_UPDATE_REMEDY };
|
|
13255
|
+
return {
|
|
13256
|
+
behind: "unknown",
|
|
13257
|
+
remedy: `${globalUpdateRemedy(hooks)} \u2014 or, if the plugin is the older one, ${PLUGIN_UPDATE_REMEDY}`
|
|
13258
|
+
};
|
|
13259
|
+
}
|
|
13260
|
+
function cliProvenance() {
|
|
13261
|
+
const envRoot = process.env.VERITY_PLUGIN_ROOT;
|
|
13262
|
+
const install = envRoot ? { pluginRoot: envRoot, version: process.env.VERITY_PLUGIN_VERSION || activePluginInstall()?.version || null } : activePluginInstall();
|
|
13263
|
+
const global = globalVerityVersion();
|
|
13264
|
+
if (!install) return { plugin: null, hooksCli: null, global, skew: null };
|
|
13265
|
+
const hooksCli = resolveHooksCli(install.pluginRoot);
|
|
13266
|
+
return {
|
|
13267
|
+
plugin: { root: install.pluginRoot, version: install.version },
|
|
13268
|
+
hooksCli,
|
|
13269
|
+
global,
|
|
13270
|
+
skew: computeSkew(global, hooksCli)
|
|
13271
|
+
};
|
|
13272
|
+
}
|
|
13273
|
+
function computeSkew(global, hooksCli) {
|
|
13274
|
+
if (!global || !hooksCli?.version) return null;
|
|
13275
|
+
if (global === hooksCli.version) return null;
|
|
13276
|
+
return { global, hooks: hooksCli.version, ...remedyFor(global, hooksCli.version) };
|
|
13277
|
+
}
|
|
13278
|
+
function cliVersionSkew() {
|
|
13279
|
+
return cliProvenance().skew;
|
|
13280
|
+
}
|
|
13281
|
+
function versionReport(p = cliProvenance()) {
|
|
13282
|
+
if (!p.plugin) return null;
|
|
13283
|
+
return {
|
|
13284
|
+
plugin: p.plugin.version,
|
|
13285
|
+
hooksCli: p.hooksCli?.version ?? null,
|
|
13286
|
+
hooksCliRung: p.hooksCli?.rung ?? null,
|
|
13287
|
+
global: p.global,
|
|
13288
|
+
skew: p.skew
|
|
13289
|
+
};
|
|
13290
|
+
}
|
|
13291
|
+
function versionLines(v) {
|
|
13292
|
+
if (!v) return { info: [], warn: [] };
|
|
13293
|
+
const plugin = v.plugin ? `plugin ${v.plugin}` : "plugin (version unreadable)";
|
|
13294
|
+
const rung = v.hooksCliRung && v.hooksCliRung !== "plugin" ? ` via ${RUNG_LABELS[v.hooksCliRung]}` : "";
|
|
13295
|
+
const hooks = v.hooksCli ? `hooks run ${CLI_PACKAGE} ${v.hooksCli}${rung}` : "hooks run a CLI whose version could not be read";
|
|
13296
|
+
if (!v.skew) {
|
|
13297
|
+
const agrees = v.global && v.hooksCli && v.global === v.hooksCli ? " \xB7 `verity` on PATH matches \u2713" : "";
|
|
13298
|
+
return { info: [` Versions: ${plugin} \xB7 ${hooks}${agrees}`], warn: [] };
|
|
13299
|
+
}
|
|
13300
|
+
return {
|
|
13301
|
+
info: [` Versions: ${plugin} \xB7 ${hooks}`],
|
|
13302
|
+
warn: [
|
|
13303
|
+
` \u26A0 \`verity\` on PATH is ${v.skew.global}, which is NOT the CLI the hooks run (${v.skew.hooks}).`,
|
|
13304
|
+
` The gate and your terminal are different builds. Fix: ${v.skew.remedy}`
|
|
13305
|
+
]
|
|
13306
|
+
};
|
|
13307
|
+
}
|
|
13308
|
+
var RUNG_LABELS = {
|
|
13309
|
+
override: "VERITY_CLI_PATH",
|
|
13310
|
+
plugin: "the plugin's node_modules",
|
|
13311
|
+
"plugin-data": "the plugin's data directory",
|
|
13312
|
+
global: "the global install on PATH"
|
|
13313
|
+
};
|
|
13314
|
+
function pluginCliInvocation() {
|
|
13315
|
+
const root = process.env.VERITY_PLUGIN_ROOT;
|
|
13316
|
+
if (!root) return null;
|
|
13317
|
+
const onPath = globalVerityVersion();
|
|
13318
|
+
if (onPath === null) return resolverCommand(root);
|
|
13319
|
+
const hooksCli = resolveHooksCli(root);
|
|
13320
|
+
if (hooksCli?.version && hooksCli.version === onPath) return null;
|
|
13321
|
+
return resolverCommand(root);
|
|
13322
|
+
}
|
|
13323
|
+
function resolverCommand(root) {
|
|
13324
|
+
return `node ${JSON.stringify((0, import_node_path9.join)(root, "scripts", "verity.mjs"))}`;
|
|
13325
|
+
}
|
|
13326
|
+
|
|
13168
13327
|
// src/commands/hooks.ts
|
|
13169
13328
|
var ALL_MOMENTS = ["stop", "pre-commit", "pre-push"];
|
|
13170
13329
|
function parseMomentSelection(raw) {
|
|
@@ -13259,6 +13418,9 @@ function registerHooksCommands(program2) {
|
|
|
13259
13418
|
const moments = status.guardOn;
|
|
13260
13419
|
const inherited = wiring.gitMoments.source === "main-worktree" && wiring.gitMoments.path ? ` (inherited from the main worktree: ${wiring.gitMoments.path})` : "";
|
|
13261
13420
|
printInfo("Wired by the Verity Claude Code plugin (not .claude/settings.json):");
|
|
13421
|
+
const versionOut = versionLines(versionReport());
|
|
13422
|
+
for (const line of versionOut.info) printInfo(line);
|
|
13423
|
+
for (const line of versionOut.warn) printWarn(line);
|
|
13262
13424
|
printInfo(" Stop hook (verity analyze): installed");
|
|
13263
13425
|
printInfo(" Intent hook (verity intent capture): installed");
|
|
13264
13426
|
printInfo(" Baseline hook (verity baseline capture): installed");
|
|
@@ -13299,7 +13461,7 @@ var import_node_crypto8 = require("node:crypto");
|
|
|
13299
13461
|
|
|
13300
13462
|
// src/lib/conversation-buffer.ts
|
|
13301
13463
|
var import_promises5 = require("node:fs/promises");
|
|
13302
|
-
var
|
|
13464
|
+
var import_node_fs9 = require("node:fs");
|
|
13303
13465
|
var import_node_child_process5 = require("node:child_process");
|
|
13304
13466
|
var import_node_crypto = require("node:crypto");
|
|
13305
13467
|
function stripImageReferences(text) {
|
|
@@ -13335,7 +13497,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
|
|
|
13335
13497
|
}
|
|
13336
13498
|
async function readAndClearConversationBuffer(currentSessionId) {
|
|
13337
13499
|
try {
|
|
13338
|
-
if ((0,
|
|
13500
|
+
if ((0, import_node_fs9.existsSync)(CONVERSATION_BUFFER_FILE)) {
|
|
13339
13501
|
const entries = await readBufferEntries();
|
|
13340
13502
|
let mine = entries;
|
|
13341
13503
|
let others = [];
|
|
@@ -13359,7 +13521,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
|
|
|
13359
13521
|
};
|
|
13360
13522
|
}
|
|
13361
13523
|
}
|
|
13362
|
-
if ((0,
|
|
13524
|
+
if ((0, import_node_fs9.existsSync)(INTENT_FILE)) {
|
|
13363
13525
|
try {
|
|
13364
13526
|
const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
|
|
13365
13527
|
await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
|
|
@@ -13652,9 +13814,9 @@ function isCommandOnlyTurn(input) {
|
|
|
13652
13814
|
|
|
13653
13815
|
// src/lib/context-identity.ts
|
|
13654
13816
|
var import_node_crypto2 = require("node:crypto");
|
|
13655
|
-
var
|
|
13656
|
-
var
|
|
13657
|
-
var
|
|
13817
|
+
var import_node_fs10 = require("node:fs");
|
|
13818
|
+
var import_node_os4 = require("node:os");
|
|
13819
|
+
var import_node_path10 = require("node:path");
|
|
13658
13820
|
var SHARED_SENTINELS = /* @__PURE__ */ new Set([
|
|
13659
13821
|
"",
|
|
13660
13822
|
"-",
|
|
@@ -13692,7 +13854,7 @@ function contextIdentity(input) {
|
|
|
13692
13854
|
if (rawTree && !isSharedSentinel(rawTree)) {
|
|
13693
13855
|
let resolved = rawTree;
|
|
13694
13856
|
try {
|
|
13695
|
-
resolved =
|
|
13857
|
+
resolved = import_node_fs10.realpathSync.native(rawTree);
|
|
13696
13858
|
} catch {
|
|
13697
13859
|
}
|
|
13698
13860
|
treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
@@ -13708,13 +13870,13 @@ function contextIdentity(input) {
|
|
|
13708
13870
|
}
|
|
13709
13871
|
function verityHome() {
|
|
13710
13872
|
const override = process.env.VERITY_HOME;
|
|
13711
|
-
return override && override.trim() ? (0,
|
|
13873
|
+
return override && override.trim() ? (0, import_node_path10.resolve)(override) : (0, import_node_path10.join)((0, import_node_os4.homedir)(), ".verity");
|
|
13712
13874
|
}
|
|
13713
13875
|
function dossierDir(identity) {
|
|
13714
|
-
return (0,
|
|
13876
|
+
return (0, import_node_path10.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
|
|
13715
13877
|
}
|
|
13716
13878
|
function treeDir(identity) {
|
|
13717
|
-
return (0,
|
|
13879
|
+
return (0, import_node_path10.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
|
|
13718
13880
|
}
|
|
13719
13881
|
function scopeIdentity(token, sessionId) {
|
|
13720
13882
|
const t = (token ?? "").trim();
|
|
@@ -13729,8 +13891,8 @@ function sessionScopeKey(token, sessionId) {
|
|
|
13729
13891
|
|
|
13730
13892
|
// src/lib/task-context-buffer.ts
|
|
13731
13893
|
var import_promises6 = require("node:fs/promises");
|
|
13732
|
-
var
|
|
13733
|
-
var
|
|
13894
|
+
var import_node_fs11 = require("node:fs");
|
|
13895
|
+
var import_node_path11 = require("node:path");
|
|
13734
13896
|
var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
|
|
13735
13897
|
var MAX_BUFFER_BYTES = 500 * 1024;
|
|
13736
13898
|
var MAX_PROMPT_CHARS = 2e3;
|
|
@@ -13769,7 +13931,7 @@ async function appendResponseToTaskBuffer(taskId, assistantResponse, actionSumma
|
|
|
13769
13931
|
}
|
|
13770
13932
|
async function readTaskContextBuffer(taskId) {
|
|
13771
13933
|
const filePath = bufferPath(taskId);
|
|
13772
|
-
if (!(0,
|
|
13934
|
+
if (!(0, import_node_fs11.existsSync)(filePath)) return null;
|
|
13773
13935
|
try {
|
|
13774
13936
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
13775
13937
|
if (!content.trim()) return null;
|
|
@@ -13803,12 +13965,12 @@ async function readTaskContextBuffer(taskId) {
|
|
|
13803
13965
|
}
|
|
13804
13966
|
async function cleanupTaskContextBuffers() {
|
|
13805
13967
|
try {
|
|
13806
|
-
if (!(0,
|
|
13968
|
+
if (!(0, import_node_fs11.existsSync)(TASK_CONTEXT_DIR)) return;
|
|
13807
13969
|
const files = await (0, import_promises6.readdir)(TASK_CONTEXT_DIR);
|
|
13808
13970
|
const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
13809
13971
|
for (const file of files) {
|
|
13810
13972
|
if (!file.endsWith(".jsonl")) continue;
|
|
13811
|
-
const filePath = (0,
|
|
13973
|
+
const filePath = (0, import_node_path11.join)(TASK_CONTEXT_DIR, file);
|
|
13812
13974
|
try {
|
|
13813
13975
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
13814
13976
|
if (stats.mtimeMs < cutoffMs) {
|
|
@@ -13822,13 +13984,13 @@ async function cleanupTaskContextBuffers() {
|
|
|
13822
13984
|
}
|
|
13823
13985
|
function bufferPath(taskId) {
|
|
13824
13986
|
const safe = taskId.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
13825
|
-
return (0,
|
|
13987
|
+
return (0, import_node_path11.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
|
|
13826
13988
|
}
|
|
13827
13989
|
async function appendEntry(taskId, entry) {
|
|
13828
13990
|
try {
|
|
13829
13991
|
await (0, import_promises6.mkdir)(TASK_CONTEXT_DIR, { recursive: true });
|
|
13830
13992
|
const filePath = bufferPath(taskId);
|
|
13831
|
-
if ((0,
|
|
13993
|
+
if ((0, import_node_fs11.existsSync)(filePath)) {
|
|
13832
13994
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
13833
13995
|
if (stats.size >= MAX_BUFFER_BYTES) {
|
|
13834
13996
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
@@ -13839,7 +14001,7 @@ async function appendEntry(taskId, entry) {
|
|
|
13839
14001
|
}
|
|
13840
14002
|
}
|
|
13841
14003
|
const line = JSON.stringify(entry) + "\n";
|
|
13842
|
-
const existing = (0,
|
|
14004
|
+
const existing = (0, import_node_fs11.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
|
|
13843
14005
|
await (0, import_promises6.writeFile)(filePath, existing + line);
|
|
13844
14006
|
} catch {
|
|
13845
14007
|
}
|
|
@@ -13847,20 +14009,20 @@ async function appendEntry(taskId, entry) {
|
|
|
13847
14009
|
|
|
13848
14010
|
// src/lib/memory-retrieval.ts
|
|
13849
14011
|
var import_promises8 = require("node:fs/promises");
|
|
13850
|
-
var
|
|
13851
|
-
var
|
|
14012
|
+
var import_node_fs13 = require("node:fs");
|
|
14013
|
+
var import_node_path13 = require("node:path");
|
|
13852
14014
|
|
|
13853
14015
|
// src/lib/org-mirror.ts
|
|
13854
|
-
var
|
|
14016
|
+
var import_node_fs12 = require("node:fs");
|
|
13855
14017
|
var import_promises7 = require("node:fs/promises");
|
|
13856
|
-
var
|
|
14018
|
+
var import_node_path12 = require("node:path");
|
|
13857
14019
|
var ORG_KINDS = ["decision", "security", "gotcha", "pattern", "domain", "integration"];
|
|
13858
14020
|
var STATE_FILE = ".org-pull-state.json";
|
|
13859
14021
|
var BODY_MAX = 8192;
|
|
13860
14022
|
function orgMirrorDir(remote = requestRemote()) {
|
|
13861
14023
|
const parsed = parseRemote(remote);
|
|
13862
14024
|
if (!parsed) return null;
|
|
13863
|
-
return (0,
|
|
14025
|
+
return (0, import_node_path12.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
|
|
13864
14026
|
}
|
|
13865
14027
|
function slugify(s) {
|
|
13866
14028
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
@@ -13926,7 +14088,7 @@ function parseOrgNode(content) {
|
|
|
13926
14088
|
}
|
|
13927
14089
|
async function readState(dir) {
|
|
13928
14090
|
try {
|
|
13929
|
-
const parsed = JSON.parse(await (0, import_promises7.readFile)((0,
|
|
14091
|
+
const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path12.join)(dir, STATE_FILE), "utf-8"));
|
|
13930
14092
|
return {
|
|
13931
14093
|
version: typeof parsed?.version === "string" ? parsed.version : null,
|
|
13932
14094
|
organization: parsed?.organization && typeof parsed.organization.id === "string" ? parsed.organization : null,
|
|
@@ -13938,7 +14100,7 @@ async function readState(dir) {
|
|
|
13938
14100
|
}
|
|
13939
14101
|
async function writeState(dir, state) {
|
|
13940
14102
|
await (0, import_promises7.mkdir)(dir, { recursive: true });
|
|
13941
|
-
await (0, import_promises7.writeFile)((0,
|
|
14103
|
+
await (0, import_promises7.writeFile)((0, import_node_path12.join)(dir, STATE_FILE), JSON.stringify({
|
|
13942
14104
|
...state.version ? { version: state.version } : {},
|
|
13943
14105
|
organization: state.organization,
|
|
13944
14106
|
pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -14003,24 +14165,24 @@ async function pullOrgKnowledge(opts) {
|
|
|
14003
14165
|
for (const n of nodes) {
|
|
14004
14166
|
const rel = orgNodePath(n);
|
|
14005
14167
|
if (written.has(rel)) continue;
|
|
14006
|
-
await (0, import_promises7.mkdir)((0,
|
|
14007
|
-
await (0, import_promises7.writeFile)((0,
|
|
14168
|
+
await (0, import_promises7.mkdir)((0, import_node_path12.join)(dir, rel.split("/")[0]), { recursive: true });
|
|
14169
|
+
await (0, import_promises7.writeFile)((0, import_node_path12.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
|
|
14008
14170
|
written.add(rel);
|
|
14009
14171
|
}
|
|
14010
14172
|
for (const rel of state.files) {
|
|
14011
|
-
if (!written.has(rel)) await (0, import_promises7.rm)((0,
|
|
14173
|
+
if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path12.join)(dir, rel), { force: true });
|
|
14012
14174
|
}
|
|
14013
|
-
await (0, import_promises7.writeFile)((0,
|
|
14175
|
+
await (0, import_promises7.writeFile)((0, import_node_path12.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
|
|
14014
14176
|
await writeState(dir, { version: org ? page.version : null, organization: org, files: [...written].sort() });
|
|
14015
14177
|
return { ok: true, status: org ? "pulled" : "none", received: nodes.length, dir };
|
|
14016
14178
|
}
|
|
14017
14179
|
async function readOrgMirror(remote = requestRemote()) {
|
|
14018
14180
|
const dir = orgMirrorDir(remote);
|
|
14019
|
-
if (!dir || !(0,
|
|
14181
|
+
if (!dir || !(0, import_node_fs12.existsSync)(dir)) return [];
|
|
14020
14182
|
const out = [];
|
|
14021
14183
|
for (const kind of ORG_KINDS) {
|
|
14022
|
-
const kindDir = (0,
|
|
14023
|
-
if (!(0,
|
|
14184
|
+
const kindDir = (0, import_node_path12.join)(dir, kind);
|
|
14185
|
+
if (!(0, import_node_fs12.existsSync)(kindDir)) continue;
|
|
14024
14186
|
let files;
|
|
14025
14187
|
try {
|
|
14026
14188
|
files = await (0, import_promises7.readdir)(kindDir);
|
|
@@ -14030,7 +14192,7 @@ async function readOrgMirror(remote = requestRemote()) {
|
|
|
14030
14192
|
for (const file of files) {
|
|
14031
14193
|
if (!file.endsWith(".md")) continue;
|
|
14032
14194
|
try {
|
|
14033
|
-
const node = parseOrgNode(await (0, import_promises7.readFile)((0,
|
|
14195
|
+
const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path12.join)(kindDir, file), "utf-8"));
|
|
14034
14196
|
if (node) out.push(node);
|
|
14035
14197
|
} catch {
|
|
14036
14198
|
}
|
|
@@ -14153,19 +14315,19 @@ function parseFrontmatter(content) {
|
|
|
14153
14315
|
return { fm, body: match[2].trim() };
|
|
14154
14316
|
}
|
|
14155
14317
|
async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
|
|
14156
|
-
const hasRepoGraph = (0,
|
|
14318
|
+
const hasRepoGraph = (0, import_node_fs13.existsSync)(memoryDir());
|
|
14157
14319
|
const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
|
|
14158
14320
|
const promptTokens = tokenize(promptText);
|
|
14159
14321
|
const nodes = [];
|
|
14160
14322
|
for (const domain of hasRepoGraph ? DOMAINS : []) {
|
|
14161
|
-
const domainDir = (0,
|
|
14162
|
-
if (!(0,
|
|
14323
|
+
const domainDir = (0, import_node_path13.join)(memoryDir(), domain);
|
|
14324
|
+
if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
|
|
14163
14325
|
try {
|
|
14164
14326
|
const files = await (0, import_promises8.readdir)(domainDir);
|
|
14165
14327
|
for (const file of files) {
|
|
14166
14328
|
if (!file.endsWith(".md")) continue;
|
|
14167
14329
|
try {
|
|
14168
|
-
const content = await (0, import_promises8.readFile)((0,
|
|
14330
|
+
const content = await (0, import_promises8.readFile)((0, import_node_path13.join)(domainDir, file), "utf-8");
|
|
14169
14331
|
const { fm, body } = parseFrontmatter(content);
|
|
14170
14332
|
if (fm.status && fm.status !== "active") continue;
|
|
14171
14333
|
nodes.push({
|
|
@@ -14232,13 +14394,13 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
14232
14394
|
|
|
14233
14395
|
// src/lib/memory-sync.ts
|
|
14234
14396
|
var import_promises9 = require("node:fs/promises");
|
|
14235
|
-
var
|
|
14236
|
-
var
|
|
14397
|
+
var import_node_fs16 = require("node:fs");
|
|
14398
|
+
var import_node_path15 = require("node:path");
|
|
14237
14399
|
var import_node_crypto3 = require("node:crypto");
|
|
14238
14400
|
|
|
14239
14401
|
// src/lib/gitignore.ts
|
|
14240
14402
|
var import_node_child_process6 = require("node:child_process");
|
|
14241
|
-
var
|
|
14403
|
+
var import_node_fs14 = require("node:fs");
|
|
14242
14404
|
var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
|
|
14243
14405
|
var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
|
|
14244
14406
|
var VERITY_GITIGNORE_BLOCK = [
|
|
@@ -14322,7 +14484,7 @@ function fenceMemoryLines(lines) {
|
|
|
14322
14484
|
function ensureVerityGitignore() {
|
|
14323
14485
|
let content = "";
|
|
14324
14486
|
try {
|
|
14325
|
-
content = (0,
|
|
14487
|
+
content = (0, import_node_fs14.readFileSync)(".gitignore", "utf-8");
|
|
14326
14488
|
} catch {
|
|
14327
14489
|
}
|
|
14328
14490
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -14349,7 +14511,7 @@ function ensureVerityGitignore() {
|
|
|
14349
14511
|
const sep4 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
14350
14512
|
text = text + sep4 + VERITY_GITIGNORE_BLOCK;
|
|
14351
14513
|
}
|
|
14352
|
-
if (text !== content) (0,
|
|
14514
|
+
if (text !== content) (0, import_node_fs14.writeFileSync)(".gitignore", text);
|
|
14353
14515
|
return verified(
|
|
14354
14516
|
memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
|
|
14355
14517
|
);
|
|
@@ -14369,7 +14531,7 @@ function untrackMemory() {
|
|
|
14369
14531
|
function writeFencedBlock() {
|
|
14370
14532
|
let content = "";
|
|
14371
14533
|
try {
|
|
14372
|
-
content = (0,
|
|
14534
|
+
content = (0, import_node_fs14.readFileSync)(".gitignore", "utf-8");
|
|
14373
14535
|
} catch {
|
|
14374
14536
|
}
|
|
14375
14537
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -14381,7 +14543,7 @@ function writeFencedBlock() {
|
|
|
14381
14543
|
text = text + sep4 + VERITY_GITIGNORE_BLOCK;
|
|
14382
14544
|
}
|
|
14383
14545
|
try {
|
|
14384
|
-
(0,
|
|
14546
|
+
(0, import_node_fs14.writeFileSync)(".gitignore", text);
|
|
14385
14547
|
return true;
|
|
14386
14548
|
} catch {
|
|
14387
14549
|
return false;
|
|
@@ -14390,14 +14552,14 @@ function writeFencedBlock() {
|
|
|
14390
14552
|
function fenceMemory() {
|
|
14391
14553
|
let original = null;
|
|
14392
14554
|
try {
|
|
14393
|
-
original = (0,
|
|
14555
|
+
original = (0, import_node_fs14.readFileSync)(".gitignore", "utf-8");
|
|
14394
14556
|
} catch {
|
|
14395
14557
|
original = null;
|
|
14396
14558
|
}
|
|
14397
14559
|
const restore = () => {
|
|
14398
14560
|
try {
|
|
14399
|
-
if (original === null) (0,
|
|
14400
|
-
else (0,
|
|
14561
|
+
if (original === null) (0, import_node_fs14.rmSync)(".gitignore", { force: true });
|
|
14562
|
+
else (0, import_node_fs14.writeFileSync)(".gitignore", original);
|
|
14401
14563
|
} catch {
|
|
14402
14564
|
}
|
|
14403
14565
|
};
|
|
@@ -14415,7 +14577,7 @@ function fenceMemory() {
|
|
|
14415
14577
|
}
|
|
14416
14578
|
function memoryOptOut() {
|
|
14417
14579
|
try {
|
|
14418
|
-
return (0,
|
|
14580
|
+
return (0, import_node_fs14.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
|
|
14419
14581
|
} catch {
|
|
14420
14582
|
return false;
|
|
14421
14583
|
}
|
|
@@ -14423,13 +14585,13 @@ function memoryOptOut() {
|
|
|
14423
14585
|
function keepMemoryTracked() {
|
|
14424
14586
|
let content = "";
|
|
14425
14587
|
try {
|
|
14426
|
-
content = (0,
|
|
14588
|
+
content = (0, import_node_fs14.readFileSync)(".gitignore", "utf-8");
|
|
14427
14589
|
} catch {
|
|
14428
14590
|
}
|
|
14429
14591
|
if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
|
|
14430
14592
|
try {
|
|
14431
14593
|
const sep4 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
|
|
14432
|
-
(0,
|
|
14594
|
+
(0, import_node_fs14.writeFileSync)(".gitignore", content + sep4 + MEMORY_OPT_OUT_STANZA);
|
|
14433
14595
|
} catch {
|
|
14434
14596
|
return "failed";
|
|
14435
14597
|
}
|
|
@@ -14464,26 +14626,26 @@ function untrackVerityState() {
|
|
|
14464
14626
|
}
|
|
14465
14627
|
|
|
14466
14628
|
// src/lib/safe-path.ts
|
|
14467
|
-
var
|
|
14468
|
-
var
|
|
14629
|
+
var import_node_fs15 = require("node:fs");
|
|
14630
|
+
var import_node_path14 = require("node:path");
|
|
14469
14631
|
function resolveInside(baseDir, candidate) {
|
|
14470
14632
|
if (typeof candidate !== "string" || candidate.length === 0) return null;
|
|
14471
|
-
if ((0,
|
|
14472
|
-
const baseAbs = (0,
|
|
14473
|
-
const full = (0,
|
|
14474
|
-
const baseSep = baseAbs.endsWith(
|
|
14633
|
+
if ((0, import_node_path14.isAbsolute)(candidate)) return null;
|
|
14634
|
+
const baseAbs = (0, import_node_path14.resolve)(baseDir);
|
|
14635
|
+
const full = (0, import_node_path14.resolve)(baseAbs, candidate);
|
|
14636
|
+
const baseSep = baseAbs.endsWith(import_node_path14.sep) ? baseAbs : baseAbs + import_node_path14.sep;
|
|
14475
14637
|
if (full !== baseAbs && !full.startsWith(baseSep)) return null;
|
|
14476
14638
|
try {
|
|
14477
|
-
if ((0,
|
|
14478
|
-
const realBase = (0,
|
|
14479
|
-
const realBaseSep = realBase.endsWith(
|
|
14639
|
+
if ((0, import_node_fs15.existsSync)(baseAbs)) {
|
|
14640
|
+
const realBase = (0, import_node_fs15.realpathSync)(baseAbs);
|
|
14641
|
+
const realBaseSep = realBase.endsWith(import_node_path14.sep) ? realBase : realBase + import_node_path14.sep;
|
|
14480
14642
|
let probe = full;
|
|
14481
|
-
while (!(0,
|
|
14482
|
-
const parent = (0,
|
|
14643
|
+
while (!(0, import_node_fs15.existsSync)(probe)) {
|
|
14644
|
+
const parent = (0, import_node_path14.dirname)(probe);
|
|
14483
14645
|
if (parent === probe) break;
|
|
14484
14646
|
probe = parent;
|
|
14485
14647
|
}
|
|
14486
|
-
const realProbe = (0,
|
|
14648
|
+
const realProbe = (0, import_node_fs15.realpathSync)(probe);
|
|
14487
14649
|
if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
|
|
14488
14650
|
}
|
|
14489
14651
|
} catch {
|
|
@@ -14491,6 +14653,42 @@ function resolveInside(baseDir, candidate) {
|
|
|
14491
14653
|
}
|
|
14492
14654
|
return full;
|
|
14493
14655
|
}
|
|
14656
|
+
var O_NOFOLLOW = typeof import_node_fs15.constants.O_NOFOLLOW === "number" ? import_node_fs15.constants.O_NOFOLLOW : 0;
|
|
14657
|
+
function readFileInside(baseDir, candidate, maxBytes) {
|
|
14658
|
+
const full = resolveInside(baseDir, candidate);
|
|
14659
|
+
if (!full) return null;
|
|
14660
|
+
let realParent;
|
|
14661
|
+
let realBase;
|
|
14662
|
+
try {
|
|
14663
|
+
realParent = (0, import_node_fs15.realpathSync)((0, import_node_path14.dirname)(full));
|
|
14664
|
+
realBase = (0, import_node_fs15.realpathSync)((0, import_node_path14.resolve)(baseDir));
|
|
14665
|
+
} catch {
|
|
14666
|
+
return null;
|
|
14667
|
+
}
|
|
14668
|
+
const realBaseSep = realBase.endsWith(import_node_path14.sep) ? realBase : realBase + import_node_path14.sep;
|
|
14669
|
+
if (realParent !== realBase && !realParent.startsWith(realBaseSep)) return null;
|
|
14670
|
+
const target = (0, import_node_path14.join)(realParent, (0, import_node_path14.basename)(full));
|
|
14671
|
+
let fd = null;
|
|
14672
|
+
try {
|
|
14673
|
+
fd = (0, import_node_fs15.openSync)(target, import_node_fs15.constants.O_RDONLY | O_NOFOLLOW);
|
|
14674
|
+
const st = (0, import_node_fs15.fstatSync)(fd);
|
|
14675
|
+
if (!st.isFile()) return null;
|
|
14676
|
+
const cap = Math.min(maxBytes, st.size);
|
|
14677
|
+
if (cap <= 0) return "";
|
|
14678
|
+
const buf = Buffer.alloc(cap);
|
|
14679
|
+
const bytesRead = (0, import_node_fs15.readSync)(fd, buf, 0, cap, 0);
|
|
14680
|
+
return buf.subarray(0, bytesRead).toString("utf-8");
|
|
14681
|
+
} catch {
|
|
14682
|
+
return null;
|
|
14683
|
+
} finally {
|
|
14684
|
+
if (fd !== null) {
|
|
14685
|
+
try {
|
|
14686
|
+
(0, import_node_fs15.closeSync)(fd);
|
|
14687
|
+
} catch {
|
|
14688
|
+
}
|
|
14689
|
+
}
|
|
14690
|
+
}
|
|
14691
|
+
}
|
|
14494
14692
|
|
|
14495
14693
|
// src/lib/glob-match.ts
|
|
14496
14694
|
function globToRegex(glob) {
|
|
@@ -14568,32 +14766,32 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
|
|
|
14568
14766
|
async function ensureMemoryDir() {
|
|
14569
14767
|
await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
|
|
14570
14768
|
for (const domain of DOMAINS2) {
|
|
14571
|
-
await (0, import_promises9.mkdir)((0,
|
|
14769
|
+
await (0, import_promises9.mkdir)((0, import_node_path15.join)(memoryDir2(), domain), { recursive: true });
|
|
14572
14770
|
}
|
|
14573
|
-
if (!(0,
|
|
14574
|
-
await (0, import_promises9.writeFile)((0,
|
|
14771
|
+
if (!(0, import_node_fs16.existsSync)((0, import_node_path15.join)(memoryDir2(), "SCHEMA.md"))) {
|
|
14772
|
+
await (0, import_promises9.writeFile)((0, import_node_path15.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
|
|
14575
14773
|
}
|
|
14576
|
-
if (!(0,
|
|
14577
|
-
await (0, import_promises9.writeFile)((0,
|
|
14774
|
+
if (!(0, import_node_fs16.existsSync)((0, import_node_path15.join)(memoryDir2(), "index.md"))) {
|
|
14775
|
+
await (0, import_promises9.writeFile)((0, import_node_path15.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
|
|
14578
14776
|
}
|
|
14579
|
-
if (!(0,
|
|
14580
|
-
await (0, import_promises9.writeFile)((0,
|
|
14777
|
+
if (!(0, import_node_fs16.existsSync)((0, import_node_path15.join)(memoryDir2(), "log.md"))) {
|
|
14778
|
+
await (0, import_promises9.writeFile)((0, import_node_path15.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
|
|
14581
14779
|
}
|
|
14582
14780
|
}
|
|
14583
14781
|
async function buildManifest() {
|
|
14584
|
-
if (!(0,
|
|
14782
|
+
if (!(0, import_node_fs16.existsSync)(memoryDir2())) {
|
|
14585
14783
|
return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
|
|
14586
14784
|
}
|
|
14587
14785
|
const nodes = [];
|
|
14588
14786
|
for (const domain of DOMAINS2) {
|
|
14589
|
-
const domainDir = (0,
|
|
14590
|
-
if (!(0,
|
|
14787
|
+
const domainDir = (0, import_node_path15.join)(memoryDir2(), domain);
|
|
14788
|
+
if (!(0, import_node_fs16.existsSync)(domainDir)) continue;
|
|
14591
14789
|
try {
|
|
14592
14790
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
14593
14791
|
for (const file of files) {
|
|
14594
14792
|
if (!file.endsWith(".md")) continue;
|
|
14595
14793
|
const filePath = `${domain}/${file}`;
|
|
14596
|
-
const fullPath = (0,
|
|
14794
|
+
const fullPath = (0, import_node_path15.join)(memoryDir2(), filePath);
|
|
14597
14795
|
try {
|
|
14598
14796
|
const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
14599
14797
|
const hash = (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
@@ -14606,13 +14804,13 @@ async function buildManifest() {
|
|
|
14606
14804
|
}
|
|
14607
14805
|
let indexHash = null;
|
|
14608
14806
|
try {
|
|
14609
|
-
const indexContent = await (0, import_promises9.readFile)((0,
|
|
14807
|
+
const indexContent = await (0, import_promises9.readFile)((0, import_node_path15.join)(memoryDir2(), "index.md"), "utf-8");
|
|
14610
14808
|
indexHash = `sha256:${(0, import_node_crypto3.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
|
|
14611
14809
|
} catch {
|
|
14612
14810
|
}
|
|
14613
14811
|
let logLength = 0;
|
|
14614
14812
|
try {
|
|
14615
|
-
const logContent = await (0, import_promises9.readFile)((0,
|
|
14813
|
+
const logContent = await (0, import_promises9.readFile)((0, import_node_path15.join)(memoryDir2(), "log.md"), "utf-8");
|
|
14616
14814
|
logLength = logContent.split("\n").length;
|
|
14617
14815
|
} catch {
|
|
14618
14816
|
}
|
|
@@ -14623,15 +14821,15 @@ function hashContent(content) {
|
|
|
14623
14821
|
}
|
|
14624
14822
|
async function readOnDiskNodes() {
|
|
14625
14823
|
const out = /* @__PURE__ */ new Map();
|
|
14626
|
-
if (!(0,
|
|
14824
|
+
if (!(0, import_node_fs16.existsSync)(memoryDir2())) return out;
|
|
14627
14825
|
for (const domain of DOMAINS2) {
|
|
14628
|
-
const domainDir = (0,
|
|
14629
|
-
if (!(0,
|
|
14826
|
+
const domainDir = (0, import_node_path15.join)(memoryDir2(), domain);
|
|
14827
|
+
if (!(0, import_node_fs16.existsSync)(domainDir)) continue;
|
|
14630
14828
|
try {
|
|
14631
14829
|
for (const file of await (0, import_promises9.readdir)(domainDir)) {
|
|
14632
14830
|
if (!file.endsWith(".md")) continue;
|
|
14633
14831
|
try {
|
|
14634
|
-
out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0,
|
|
14832
|
+
out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path15.join)(domainDir, file), "utf-8")));
|
|
14635
14833
|
} catch {
|
|
14636
14834
|
}
|
|
14637
14835
|
}
|
|
@@ -14668,7 +14866,7 @@ async function recordSyncedNodePaths() {
|
|
|
14668
14866
|
}
|
|
14669
14867
|
}
|
|
14670
14868
|
async function writeFileAtomic(path, content) {
|
|
14671
|
-
await (0, import_promises9.mkdir)((0,
|
|
14869
|
+
await (0, import_promises9.mkdir)((0, import_node_path15.dirname)(path), { recursive: true });
|
|
14672
14870
|
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
14673
14871
|
await (0, import_promises9.writeFile)(tmp, content);
|
|
14674
14872
|
await (0, import_promises9.rename)(tmp, path);
|
|
@@ -14682,8 +14880,8 @@ async function computeEditedNodeUploads() {
|
|
|
14682
14880
|
const uploads = [];
|
|
14683
14881
|
for (const [path, prevHash] of prev) {
|
|
14684
14882
|
if (prevHash == null) continue;
|
|
14685
|
-
const full = (0,
|
|
14686
|
-
if (!(0,
|
|
14883
|
+
const full = (0, import_node_path15.join)(memoryDir2(), path);
|
|
14884
|
+
if (!(0, import_node_fs16.existsSync)(full)) continue;
|
|
14687
14885
|
let content;
|
|
14688
14886
|
try {
|
|
14689
14887
|
content = await (0, import_promises9.readFile)(full, "utf-8");
|
|
@@ -14727,8 +14925,8 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
14727
14925
|
const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
|
|
14728
14926
|
for (const n of notes) logLines.push(` - ${n}`);
|
|
14729
14927
|
try {
|
|
14730
|
-
const existing = (0,
|
|
14731
|
-
await (0, import_promises9.writeFile)((0,
|
|
14928
|
+
const existing = (0, import_node_fs16.existsSync)((0, import_node_path15.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path15.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
|
|
14929
|
+
await (0, import_promises9.writeFile)((0, import_node_path15.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
|
|
14732
14930
|
} catch {
|
|
14733
14931
|
}
|
|
14734
14932
|
if (opts.baseline === "written") await mergeSyncBaseline(synced);
|
|
@@ -14738,7 +14936,7 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
14738
14936
|
async function mergeSyncBaseline(entries) {
|
|
14739
14937
|
if (entries.size === 0) return;
|
|
14740
14938
|
try {
|
|
14741
|
-
if ((0,
|
|
14939
|
+
if ((0, import_node_fs16.existsSync)(syncStateFile())) {
|
|
14742
14940
|
try {
|
|
14743
14941
|
JSON.parse(await (0, import_promises9.readFile)(syncStateFile(), "utf-8"));
|
|
14744
14942
|
} catch {
|
|
@@ -14766,7 +14964,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
14766
14964
|
notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
|
|
14767
14965
|
}
|
|
14768
14966
|
}
|
|
14769
|
-
if ((0,
|
|
14967
|
+
if ((0, import_node_fs16.existsSync)(fullPath)) {
|
|
14770
14968
|
let existing = "";
|
|
14771
14969
|
try {
|
|
14772
14970
|
existing = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
@@ -14782,7 +14980,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
14782
14980
|
notes.push(`${write.path}: updated from server (untouched here since the server delivered it)`);
|
|
14783
14981
|
}
|
|
14784
14982
|
}
|
|
14785
|
-
await (0, import_promises9.mkdir)((0,
|
|
14983
|
+
await (0, import_promises9.mkdir)((0, import_node_path15.dirname)(fullPath), { recursive: true });
|
|
14786
14984
|
await (0, import_promises9.writeFile)(fullPath, content);
|
|
14787
14985
|
return { written: true, syncedHash: hashContent(content), notes };
|
|
14788
14986
|
}
|
|
@@ -14823,8 +15021,8 @@ async function regenerateIndex() {
|
|
|
14823
15021
|
];
|
|
14824
15022
|
let totalNodes = 0;
|
|
14825
15023
|
for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
|
|
14826
|
-
const domainDir = (0,
|
|
14827
|
-
if (!(0,
|
|
15024
|
+
const domainDir = (0, import_node_path15.join)(memoryDir2(), domain);
|
|
15025
|
+
if (!(0, import_node_fs16.existsSync)(domainDir)) continue;
|
|
14828
15026
|
try {
|
|
14829
15027
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
14830
15028
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
@@ -14834,7 +15032,7 @@ async function regenerateIndex() {
|
|
|
14834
15032
|
for (const file of mdFiles.sort()) {
|
|
14835
15033
|
const slug = file.replace(/\.md$/, "");
|
|
14836
15034
|
try {
|
|
14837
|
-
const content = await (0, import_promises9.readFile)((0,
|
|
15035
|
+
const content = await (0, import_promises9.readFile)((0, import_node_path15.join)(domainDir, file), "utf-8");
|
|
14838
15036
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
14839
15037
|
const kind = pickFrontmatter(content, "kind") ?? "-";
|
|
14840
15038
|
const confidence = pickFrontmatter(content, "confidence");
|
|
@@ -14858,7 +15056,7 @@ async function regenerateIndex() {
|
|
|
14858
15056
|
lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
|
|
14859
15057
|
}
|
|
14860
15058
|
const next = lines.join("\n") + "\n";
|
|
14861
|
-
const indexPath = (0,
|
|
15059
|
+
const indexPath = (0, import_node_path15.join)(memoryDir2(), "index.md");
|
|
14862
15060
|
let existing = null;
|
|
14863
15061
|
try {
|
|
14864
15062
|
existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
|
|
@@ -15255,9 +15453,9 @@ function hasLegacyMemoryBlock(text) {
|
|
|
15255
15453
|
return findMarker(text, LEGACY_MD_START) !== -1;
|
|
15256
15454
|
}
|
|
15257
15455
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
15258
|
-
const claudeMdPath = (0,
|
|
15456
|
+
const claudeMdPath = (0, import_node_path15.join)(cwd, "CLAUDE.md");
|
|
15259
15457
|
let existing = "";
|
|
15260
|
-
if ((0,
|
|
15458
|
+
if ((0, import_node_fs16.existsSync)(claudeMdPath)) {
|
|
15261
15459
|
existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
|
|
15262
15460
|
}
|
|
15263
15461
|
let startTag = CLAUDE_MD_START;
|
|
@@ -15398,9 +15596,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
|
|
|
15398
15596
|
`;
|
|
15399
15597
|
|
|
15400
15598
|
// src/lib/dossier-session.ts
|
|
15401
|
-
var
|
|
15599
|
+
var import_node_fs21 = require("node:fs");
|
|
15402
15600
|
var import_node_crypto7 = require("node:crypto");
|
|
15403
|
-
var
|
|
15601
|
+
var import_node_path18 = require("node:path");
|
|
15404
15602
|
|
|
15405
15603
|
// src/lib/pending-repeat.ts
|
|
15406
15604
|
var STOP = /* @__PURE__ */ new Set([
|
|
@@ -15505,8 +15703,8 @@ function statementAnchorKey(file, patternId) {
|
|
|
15505
15703
|
|
|
15506
15704
|
// src/lib/dossier/log.ts
|
|
15507
15705
|
var import_node_crypto4 = require("node:crypto");
|
|
15508
|
-
var
|
|
15509
|
-
var
|
|
15706
|
+
var import_node_fs17 = require("node:fs");
|
|
15707
|
+
var import_node_path16 = require("node:path");
|
|
15510
15708
|
var CRC_TABLE = (() => {
|
|
15511
15709
|
const t = new Int32Array(256);
|
|
15512
15710
|
for (let i = 0; i < 256; i++) {
|
|
@@ -15525,13 +15723,13 @@ function crc32(s) {
|
|
|
15525
15723
|
function openDossier(identity) {
|
|
15526
15724
|
try {
|
|
15527
15725
|
const dir = dossierDir(identity);
|
|
15528
|
-
(0,
|
|
15726
|
+
(0, import_node_fs17.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
15529
15727
|
return {
|
|
15530
15728
|
dir,
|
|
15531
15729
|
identity,
|
|
15532
|
-
eventsPath: (0,
|
|
15533
|
-
foldPath: (0,
|
|
15534
|
-
rotatedDir: (0,
|
|
15730
|
+
eventsPath: (0, import_node_path16.join)(dir, "events.jsonl"),
|
|
15731
|
+
foldPath: (0, import_node_path16.join)(dir, "fold.json"),
|
|
15732
|
+
rotatedDir: (0, import_node_path16.join)(dir, "rotated")
|
|
15535
15733
|
};
|
|
15536
15734
|
} catch {
|
|
15537
15735
|
return null;
|
|
@@ -15593,7 +15791,7 @@ function appendEvent(d, ev) {
|
|
|
15593
15791
|
at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
15594
15792
|
...ev
|
|
15595
15793
|
});
|
|
15596
|
-
(0,
|
|
15794
|
+
(0, import_node_fs17.appendFileSync)(d.eventsPath, line, { mode: 384 });
|
|
15597
15795
|
return true;
|
|
15598
15796
|
} catch {
|
|
15599
15797
|
return false;
|
|
@@ -15601,14 +15799,14 @@ function appendEvent(d, ev) {
|
|
|
15601
15799
|
}
|
|
15602
15800
|
function rotateIfNeeded2(d) {
|
|
15603
15801
|
try {
|
|
15604
|
-
if (!(0,
|
|
15605
|
-
if ((0,
|
|
15606
|
-
(0,
|
|
15607
|
-
(0,
|
|
15608
|
-
const kept = (0,
|
|
15802
|
+
if (!(0, import_node_fs17.existsSync)(d.eventsPath)) return;
|
|
15803
|
+
if ((0, import_node_fs17.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
|
|
15804
|
+
(0, import_node_fs17.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
|
|
15805
|
+
(0, import_node_fs17.renameSync)(d.eventsPath, (0, import_node_path16.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
|
|
15806
|
+
const kept = (0, import_node_fs17.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
15609
15807
|
for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
|
|
15610
15808
|
try {
|
|
15611
|
-
(0,
|
|
15809
|
+
(0, import_node_fs17.renameSync)((0, import_node_path16.join)(d.rotatedDir, stale), (0, import_node_path16.join)(d.rotatedDir, `${stale}.pruned`));
|
|
15612
15810
|
} catch {
|
|
15613
15811
|
}
|
|
15614
15812
|
}
|
|
@@ -15618,8 +15816,8 @@ function rotateIfNeeded2(d) {
|
|
|
15618
15816
|
|
|
15619
15817
|
// src/lib/dossier/fold-dossier.ts
|
|
15620
15818
|
var import_node_crypto5 = require("node:crypto");
|
|
15621
|
-
var
|
|
15622
|
-
var
|
|
15819
|
+
var import_node_fs18 = require("node:fs");
|
|
15820
|
+
var import_node_path17 = require("node:path");
|
|
15623
15821
|
var EMPTY_CAPABILITIES = () => ({
|
|
15624
15822
|
human_reachable: { value: "unknown", tier: "unknown" },
|
|
15625
15823
|
authorship_observability: { value: "unknown", tier: "unknown" },
|
|
@@ -15670,12 +15868,12 @@ function foldDossier(d, opts = {}) {
|
|
|
15670
15868
|
}
|
|
15671
15869
|
};
|
|
15672
15870
|
try {
|
|
15673
|
-
if ((0,
|
|
15674
|
-
const files = (0,
|
|
15871
|
+
if ((0, import_node_fs18.existsSync)(d.rotatedDir)) {
|
|
15872
|
+
const files = (0, import_node_fs18.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
15675
15873
|
state.meta.rotations = files.length;
|
|
15676
15874
|
for (const f of files) {
|
|
15677
15875
|
try {
|
|
15678
|
-
ingest((0,
|
|
15876
|
+
ingest((0, import_node_fs18.readFileSync)((0, import_node_path17.join)(d.rotatedDir, f), "utf8"));
|
|
15679
15877
|
} catch {
|
|
15680
15878
|
state.meta.dropped_lines++;
|
|
15681
15879
|
}
|
|
@@ -15684,9 +15882,9 @@ function foldDossier(d, opts = {}) {
|
|
|
15684
15882
|
} catch {
|
|
15685
15883
|
}
|
|
15686
15884
|
try {
|
|
15687
|
-
if ((0,
|
|
15688
|
-
state.meta.upto_offset = (0,
|
|
15689
|
-
ingest((0,
|
|
15885
|
+
if ((0, import_node_fs18.existsSync)(d.eventsPath)) {
|
|
15886
|
+
state.meta.upto_offset = (0, import_node_fs18.statSync)(d.eventsPath).size;
|
|
15887
|
+
ingest((0, import_node_fs18.readFileSync)(d.eventsPath, "utf8"));
|
|
15690
15888
|
}
|
|
15691
15889
|
} catch {
|
|
15692
15890
|
}
|
|
@@ -15957,7 +16155,7 @@ function applyBounds(state, input) {
|
|
|
15957
16155
|
}
|
|
15958
16156
|
|
|
15959
16157
|
// src/lib/dossier/cache.ts
|
|
15960
|
-
var
|
|
16158
|
+
var import_node_fs19 = require("node:fs");
|
|
15961
16159
|
function compactState(s) {
|
|
15962
16160
|
const ms = (iso) => Date.parse(iso) || 0;
|
|
15963
16161
|
return {
|
|
@@ -16086,20 +16284,20 @@ function encodeState(s) {
|
|
|
16086
16284
|
function writeFoldCache(d, state) {
|
|
16087
16285
|
try {
|
|
16088
16286
|
const tmp = `${d.foldPath}.${process.pid}.tmp`;
|
|
16089
|
-
(0,
|
|
16090
|
-
(0,
|
|
16287
|
+
(0, import_node_fs19.writeFileSync)(tmp, encodeState(state), { mode: 384 });
|
|
16288
|
+
(0, import_node_fs19.renameSync)(tmp, d.foldPath);
|
|
16091
16289
|
} catch {
|
|
16092
16290
|
}
|
|
16093
16291
|
}
|
|
16094
16292
|
function readFoldCache(d) {
|
|
16095
16293
|
try {
|
|
16096
|
-
if (!(0,
|
|
16097
|
-
const raw = JSON.parse((0,
|
|
16294
|
+
if (!(0, import_node_fs19.existsSync)(d.foldPath)) return null;
|
|
16295
|
+
const raw = JSON.parse((0, import_node_fs19.readFileSync)(d.foldPath, "utf8"));
|
|
16098
16296
|
if (raw?.v !== 1) return null;
|
|
16099
16297
|
const cached2 = expandState(raw);
|
|
16100
16298
|
if (!cached2?.meta) return null;
|
|
16101
|
-
const size = (0,
|
|
16102
|
-
const rotations = (0,
|
|
16299
|
+
const size = (0, import_node_fs19.existsSync)(d.eventsPath) ? (0, import_node_fs19.statSync)(d.eventsPath).size : 0;
|
|
16300
|
+
const rotations = (0, import_node_fs19.existsSync)(d.rotatedDir) ? (0, import_node_fs19.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
|
|
16103
16301
|
if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
|
|
16104
16302
|
return cached2;
|
|
16105
16303
|
} catch {
|
|
@@ -16150,13 +16348,13 @@ function assessContinuity(i) {
|
|
|
16150
16348
|
|
|
16151
16349
|
// src/lib/dossier/reanchor.ts
|
|
16152
16350
|
var import_node_crypto6 = require("node:crypto");
|
|
16153
|
-
var
|
|
16351
|
+
var import_node_fs20 = require("node:fs");
|
|
16154
16352
|
function lineSha(text) {
|
|
16155
16353
|
return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
|
|
16156
16354
|
}
|
|
16157
16355
|
function fileHash(path) {
|
|
16158
16356
|
try {
|
|
16159
|
-
return (0, import_node_crypto6.createHash)("sha256").update((0,
|
|
16357
|
+
return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs20.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
|
|
16160
16358
|
} catch {
|
|
16161
16359
|
return null;
|
|
16162
16360
|
}
|
|
@@ -16528,20 +16726,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
|
|
|
16528
16726
|
let sessions = 0;
|
|
16529
16727
|
try {
|
|
16530
16728
|
const dir = treeDir(identity);
|
|
16531
|
-
if (!(0,
|
|
16532
|
-
for (const entry of (0,
|
|
16729
|
+
if (!(0, import_node_fs21.existsSync)(dir)) return { paths: [], sessions: 0 };
|
|
16730
|
+
for (const entry of (0, import_node_fs21.readdirSync)(dir, { withFileTypes: true })) {
|
|
16533
16731
|
if (!entry.isDirectory()) continue;
|
|
16534
16732
|
if (entry.name === identity.sessionKey) continue;
|
|
16535
|
-
const log = (0,
|
|
16733
|
+
const log = (0, import_node_path18.join)(dir, entry.name, "events.jsonl");
|
|
16536
16734
|
try {
|
|
16537
|
-
if (!(0,
|
|
16538
|
-
if (now - (0,
|
|
16735
|
+
if (!(0, import_node_fs21.existsSync)(log)) continue;
|
|
16736
|
+
if (now - (0, import_node_fs21.statSync)(log).mtimeMs > windowMs) continue;
|
|
16539
16737
|
const sib = {
|
|
16540
|
-
dir: (0,
|
|
16738
|
+
dir: (0, import_node_path18.join)(dir, entry.name),
|
|
16541
16739
|
identity,
|
|
16542
16740
|
eventsPath: log,
|
|
16543
|
-
foldPath: (0,
|
|
16544
|
-
rotatedDir: (0,
|
|
16741
|
+
foldPath: (0, import_node_path18.join)(dir, entry.name, "fold.json"),
|
|
16742
|
+
rotatedDir: (0, import_node_path18.join)(dir, entry.name, "rotated")
|
|
16545
16743
|
};
|
|
16546
16744
|
const state = readFoldCache(sib) ?? foldDossier(sib);
|
|
16547
16745
|
sessions++;
|
|
@@ -16569,25 +16767,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
16569
16767
|
let removed = 0;
|
|
16570
16768
|
try {
|
|
16571
16769
|
const mine = dossierDir(identity);
|
|
16572
|
-
const userDir = (0,
|
|
16573
|
-
if (!(0,
|
|
16770
|
+
const userDir = (0, import_node_path18.dirname)((0, import_node_path18.dirname)(mine));
|
|
16771
|
+
if (!(0, import_node_fs21.existsSync)(userDir)) return 0;
|
|
16574
16772
|
const cutoff = Date.now() - maxAgeMs;
|
|
16575
|
-
for (const tree of (0,
|
|
16773
|
+
for (const tree of (0, import_node_fs21.readdirSync)(userDir, { withFileTypes: true })) {
|
|
16576
16774
|
if (!tree.isDirectory()) continue;
|
|
16577
|
-
const treePath = (0,
|
|
16775
|
+
const treePath = (0, import_node_path18.join)(userDir, tree.name);
|
|
16578
16776
|
let live = 0;
|
|
16579
|
-
for (const entry of (0,
|
|
16777
|
+
for (const entry of (0, import_node_fs21.readdirSync)(treePath, { withFileTypes: true })) {
|
|
16580
16778
|
if (!entry.isDirectory()) continue;
|
|
16581
|
-
const dir = (0,
|
|
16779
|
+
const dir = (0, import_node_path18.join)(treePath, entry.name);
|
|
16582
16780
|
if (dir === mine) {
|
|
16583
16781
|
live++;
|
|
16584
16782
|
continue;
|
|
16585
16783
|
}
|
|
16586
16784
|
try {
|
|
16587
|
-
const log = (0,
|
|
16588
|
-
const at = (0,
|
|
16785
|
+
const log = (0, import_node_path18.join)(dir, "events.jsonl");
|
|
16786
|
+
const at = (0, import_node_fs21.existsSync)(log) ? (0, import_node_fs21.statSync)(log).mtimeMs : (0, import_node_fs21.statSync)(dir).mtimeMs;
|
|
16589
16787
|
if (at < cutoff) {
|
|
16590
|
-
(0,
|
|
16788
|
+
(0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
|
|
16591
16789
|
removed++;
|
|
16592
16790
|
} else {
|
|
16593
16791
|
live++;
|
|
@@ -16597,7 +16795,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
16597
16795
|
}
|
|
16598
16796
|
if (live === 0) {
|
|
16599
16797
|
try {
|
|
16600
|
-
(0,
|
|
16798
|
+
(0, import_node_fs21.rmSync)(treePath, { recursive: false, force: false });
|
|
16601
16799
|
} catch {
|
|
16602
16800
|
}
|
|
16603
16801
|
}
|
|
@@ -16614,8 +16812,8 @@ function sessionDossier(token, sessionId) {
|
|
|
16614
16812
|
}
|
|
16615
16813
|
function hasActiveGoal(d) {
|
|
16616
16814
|
try {
|
|
16617
|
-
if (!(0,
|
|
16618
|
-
return (0,
|
|
16815
|
+
if (!(0, import_node_fs21.existsSync)(d.eventsPath)) return false;
|
|
16816
|
+
return (0, import_node_fs21.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
|
|
16619
16817
|
} catch {
|
|
16620
16818
|
return false;
|
|
16621
16819
|
}
|
|
@@ -16639,7 +16837,7 @@ function recordTurn(d, t) {
|
|
|
16639
16837
|
for (const a of t.authored) {
|
|
16640
16838
|
const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
|
|
16641
16839
|
const prior = t.known?.authored?.get(a.p);
|
|
16642
|
-
const hash = fileHash((0,
|
|
16840
|
+
const hash = fileHash((0, import_node_path18.join)(root, a.p));
|
|
16643
16841
|
const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
|
|
16644
16842
|
const adds = Math.max(0, a.a - (prior?.adds ?? 0));
|
|
16645
16843
|
const dels = Math.max(0, a.d - (prior?.dels ?? 0));
|
|
@@ -16672,7 +16870,7 @@ function recordTurn(d, t) {
|
|
|
16672
16870
|
}
|
|
16673
16871
|
const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
|
|
16674
16872
|
for (const u of t.unobserved) {
|
|
16675
|
-
const hash = fileHash((0,
|
|
16873
|
+
const hash = fileHash((0, import_node_path18.join)(root, u.p));
|
|
16676
16874
|
if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
|
|
16677
16875
|
appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
|
|
16678
16876
|
}
|
|
@@ -16707,8 +16905,8 @@ function recordVerdict(d, v) {
|
|
|
16707
16905
|
if (!sent.has(f.file)) continue;
|
|
16708
16906
|
if (!lines.has(f.file)) {
|
|
16709
16907
|
try {
|
|
16710
|
-
const abs = (0,
|
|
16711
|
-
lines.set(f.file, (0,
|
|
16908
|
+
const abs = (0, import_node_path18.join)(root, f.file);
|
|
16909
|
+
lines.set(f.file, (0, import_node_fs21.existsSync)(abs) ? (0, import_node_fs21.readFileSync)(abs, "utf8").split("\n") : null);
|
|
16712
16910
|
} catch {
|
|
16713
16911
|
lines.set(f.file, null);
|
|
16714
16912
|
}
|
|
@@ -16808,8 +17006,8 @@ function recallMemory(d, identity, opts) {
|
|
|
16808
17006
|
budgetBytes: opts.budgetBytes,
|
|
16809
17007
|
readFileLines: (file) => {
|
|
16810
17008
|
try {
|
|
16811
|
-
const abs = (0,
|
|
16812
|
-
return (0,
|
|
17009
|
+
const abs = (0, import_node_path18.join)(root, file);
|
|
17010
|
+
return (0, import_node_fs21.existsSync)(abs) ? (0, import_node_fs21.readFileSync)(abs, "utf8").split("\n") : null;
|
|
16813
17011
|
} catch {
|
|
16814
17012
|
return null;
|
|
16815
17013
|
}
|
|
@@ -16953,46 +17151,46 @@ async function fireClassify(prompt, sessionId, globals) {
|
|
|
16953
17151
|
}
|
|
16954
17152
|
|
|
16955
17153
|
// src/commands/lifecycle.ts
|
|
16956
|
-
var
|
|
16957
|
-
var
|
|
17154
|
+
var import_node_fs25 = require("node:fs");
|
|
17155
|
+
var import_node_path23 = require("node:path");
|
|
16958
17156
|
|
|
16959
17157
|
// src/lib/baseline.ts
|
|
16960
|
-
var
|
|
16961
|
-
var
|
|
17158
|
+
var import_node_fs24 = require("node:fs");
|
|
17159
|
+
var import_node_path22 = require("node:path");
|
|
16962
17160
|
var import_node_crypto9 = require("node:crypto");
|
|
16963
17161
|
|
|
16964
17162
|
// src/lib/snapshot.ts
|
|
16965
|
-
var
|
|
16966
|
-
var
|
|
17163
|
+
var import_node_fs23 = require("node:fs");
|
|
17164
|
+
var import_node_path21 = require("node:path");
|
|
16967
17165
|
var import_node_child_process7 = require("node:child_process");
|
|
16968
17166
|
|
|
16969
17167
|
// src/lib/files.ts
|
|
16970
|
-
var
|
|
17168
|
+
var import_node_path20 = require("node:path");
|
|
16971
17169
|
|
|
16972
17170
|
// src/lib/safe-read.ts
|
|
16973
|
-
var
|
|
16974
|
-
var
|
|
16975
|
-
var FLAGS =
|
|
17171
|
+
var import_node_fs22 = require("node:fs");
|
|
17172
|
+
var import_node_path19 = require("node:path");
|
|
17173
|
+
var FLAGS = import_node_fs22.constants;
|
|
16976
17174
|
var NOFOLLOW = FLAGS.O_NOFOLLOW;
|
|
16977
17175
|
var NONBLOCK = FLAGS.O_NONBLOCK;
|
|
16978
17176
|
function closeOpened(fd) {
|
|
16979
17177
|
try {
|
|
16980
|
-
(0,
|
|
17178
|
+
(0, import_node_fs22.closeSync)(fd);
|
|
16981
17179
|
} catch {
|
|
16982
17180
|
}
|
|
16983
17181
|
}
|
|
16984
17182
|
function isInsideRoot(realRoot, realPath) {
|
|
16985
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
17183
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path19.sep) ? realRoot : realRoot + import_node_path19.sep);
|
|
16986
17184
|
}
|
|
16987
17185
|
function sameOpenedFile(opened, current, nofollowAvailable) {
|
|
16988
17186
|
if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
|
|
16989
17187
|
return opened.ino === current.ino && opened.dev === current.dev;
|
|
16990
17188
|
}
|
|
16991
17189
|
function openRegularInRoot(root, path) {
|
|
16992
|
-
const full = (0,
|
|
17190
|
+
const full = (0, import_node_path19.isAbsolute)(path) ? path : (0, import_node_path19.join)(root, path);
|
|
16993
17191
|
let fd;
|
|
16994
17192
|
try {
|
|
16995
|
-
fd = (0,
|
|
17193
|
+
fd = (0, import_node_fs22.openSync)(full, import_node_fs22.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
|
|
16996
17194
|
} catch (err) {
|
|
16997
17195
|
const code = err.code;
|
|
16998
17196
|
if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
|
|
@@ -17000,18 +17198,18 @@ function openRegularInRoot(root, path) {
|
|
|
17000
17198
|
return { ok: false, reason: "unreadable" };
|
|
17001
17199
|
}
|
|
17002
17200
|
try {
|
|
17003
|
-
const opened = (0,
|
|
17201
|
+
const opened = (0, import_node_fs22.fstatSync)(fd, { bigint: true });
|
|
17004
17202
|
if (!opened.isFile()) {
|
|
17005
17203
|
closeOpened(fd);
|
|
17006
17204
|
return { ok: false, reason: "not-regular" };
|
|
17007
17205
|
}
|
|
17008
|
-
const realRoot =
|
|
17009
|
-
const realPath =
|
|
17206
|
+
const realRoot = import_node_fs22.realpathSync.native(root);
|
|
17207
|
+
const realPath = import_node_fs22.realpathSync.native(full);
|
|
17010
17208
|
if (!isInsideRoot(realRoot, realPath)) {
|
|
17011
17209
|
closeOpened(fd);
|
|
17012
17210
|
return { ok: false, reason: "outside-root" };
|
|
17013
17211
|
}
|
|
17014
|
-
const current = (0,
|
|
17212
|
+
const current = (0, import_node_fs22.statSync)(realPath, { bigint: true });
|
|
17015
17213
|
if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
|
|
17016
17214
|
closeOpened(fd);
|
|
17017
17215
|
return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
|
|
@@ -17033,7 +17231,7 @@ function readOpened(fd, size) {
|
|
|
17033
17231
|
const buffer = Buffer.alloc(size);
|
|
17034
17232
|
let offset = 0;
|
|
17035
17233
|
while (offset < size) {
|
|
17036
|
-
const n = (0,
|
|
17234
|
+
const n = (0, import_node_fs22.readSync)(fd, buffer, offset, size - offset, offset);
|
|
17037
17235
|
if (n === 0) break;
|
|
17038
17236
|
offset += n;
|
|
17039
17237
|
}
|
|
@@ -17127,7 +17325,7 @@ var LANG_MAP = {
|
|
|
17127
17325
|
mk: "make"
|
|
17128
17326
|
};
|
|
17129
17327
|
function detectLanguage(filepath) {
|
|
17130
|
-
const ext = (0,
|
|
17328
|
+
const ext = (0, import_node_path20.extname)(filepath).slice(1);
|
|
17131
17329
|
return LANG_MAP[ext] ?? ext;
|
|
17132
17330
|
}
|
|
17133
17331
|
function sortByMtime(files) {
|
|
@@ -17218,16 +17416,16 @@ function collectCodeDelta(files, opts) {
|
|
|
17218
17416
|
|
|
17219
17417
|
// src/lib/snapshot.ts
|
|
17220
17418
|
function generateSnapshotDiffs(files) {
|
|
17221
|
-
if (!(0,
|
|
17419
|
+
if (!(0, import_node_fs23.existsSync)(SNAPSHOT_DIR)) {
|
|
17222
17420
|
return { diffs: [], has_snapshots: false };
|
|
17223
17421
|
}
|
|
17224
17422
|
const diffs = [];
|
|
17225
17423
|
for (const file of files) {
|
|
17226
17424
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
17227
|
-
const snapshotPath = (0,
|
|
17425
|
+
const snapshotPath = (0, import_node_path21.join)(SNAPSHOT_DIR, file.path);
|
|
17228
17426
|
const language = file.language ?? detectLanguage(file.path);
|
|
17229
|
-
if ((0,
|
|
17230
|
-
const oldContent = (0,
|
|
17427
|
+
if ((0, import_node_fs23.existsSync)(snapshotPath)) {
|
|
17428
|
+
const oldContent = (0, import_node_fs23.readFileSync)(snapshotPath, "utf-8");
|
|
17231
17429
|
if (oldContent === file.content) continue;
|
|
17232
17430
|
const diff = computeDiff(oldContent, file.content, file.path);
|
|
17233
17431
|
if (diff) {
|
|
@@ -17252,20 +17450,20 @@ function saveSnapshots(files) {
|
|
|
17252
17450
|
const snapshotPaths = /* @__PURE__ */ new Set();
|
|
17253
17451
|
for (const file of files) {
|
|
17254
17452
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
17255
|
-
const snapshotPath = (0,
|
|
17453
|
+
const snapshotPath = (0, import_node_path21.join)(SNAPSHOT_DIR, file.path);
|
|
17256
17454
|
snapshotPaths.add(snapshotPath);
|
|
17257
|
-
(0,
|
|
17258
|
-
(0,
|
|
17455
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path21.dirname)(snapshotPath), { recursive: true });
|
|
17456
|
+
(0, import_node_fs23.writeFileSync)(snapshotPath, file.content);
|
|
17259
17457
|
}
|
|
17260
17458
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
17261
17459
|
}
|
|
17262
17460
|
function computeDiff(oldContent, newContent, filePath) {
|
|
17263
|
-
const tmpOld = (0,
|
|
17264
|
-
const tmpNew = (0,
|
|
17461
|
+
const tmpOld = (0, import_node_path21.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
17462
|
+
const tmpNew = (0, import_node_path21.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
17265
17463
|
try {
|
|
17266
|
-
(0,
|
|
17267
|
-
(0,
|
|
17268
|
-
(0,
|
|
17464
|
+
(0, import_node_fs23.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
17465
|
+
(0, import_node_fs23.writeFileSync)(tmpOld, oldContent);
|
|
17466
|
+
(0, import_node_fs23.writeFileSync)(tmpNew, newContent);
|
|
17269
17467
|
const result = (0, import_node_child_process7.execSync)(
|
|
17270
17468
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
17271
17469
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -17279,32 +17477,32 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
17279
17477
|
return null;
|
|
17280
17478
|
} finally {
|
|
17281
17479
|
try {
|
|
17282
|
-
(0,
|
|
17480
|
+
(0, import_node_fs23.unlinkSync)(tmpOld);
|
|
17283
17481
|
} catch {
|
|
17284
17482
|
}
|
|
17285
17483
|
try {
|
|
17286
|
-
(0,
|
|
17484
|
+
(0, import_node_fs23.unlinkSync)(tmpNew);
|
|
17287
17485
|
} catch {
|
|
17288
17486
|
}
|
|
17289
17487
|
}
|
|
17290
17488
|
}
|
|
17291
17489
|
function cleanStaleSnapshots(dir, keepSet) {
|
|
17292
|
-
if (!(0,
|
|
17490
|
+
if (!(0, import_node_fs23.existsSync)(dir)) return;
|
|
17293
17491
|
try {
|
|
17294
|
-
const entries = (0,
|
|
17492
|
+
const entries = (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true });
|
|
17295
17493
|
for (const entry of entries) {
|
|
17296
17494
|
if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
|
|
17297
|
-
const fullPath = (0,
|
|
17495
|
+
const fullPath = (0, import_node_path21.join)(dir, entry.name);
|
|
17298
17496
|
if (entry.isDirectory()) {
|
|
17299
17497
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
17300
17498
|
try {
|
|
17301
|
-
const remaining = (0,
|
|
17302
|
-
if (remaining.length === 0) (0,
|
|
17499
|
+
const remaining = (0, import_node_fs23.readdirSync)(fullPath);
|
|
17500
|
+
if (remaining.length === 0) (0, import_node_fs23.rmdirSync)(fullPath);
|
|
17303
17501
|
} catch {
|
|
17304
17502
|
}
|
|
17305
17503
|
} else if (!keepSet.has(fullPath)) {
|
|
17306
17504
|
try {
|
|
17307
|
-
(0,
|
|
17505
|
+
(0, import_node_fs23.unlinkSync)(fullPath);
|
|
17308
17506
|
} catch {
|
|
17309
17507
|
}
|
|
17310
17508
|
}
|
|
@@ -17323,20 +17521,20 @@ function sessionKey(sessionId) {
|
|
|
17323
17521
|
return (0, import_node_crypto9.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
17324
17522
|
}
|
|
17325
17523
|
function sessionDir(key) {
|
|
17326
|
-
return (0,
|
|
17524
|
+
return (0, import_node_path22.join)(projectPath(BASELINE_DIR), key);
|
|
17327
17525
|
}
|
|
17328
17526
|
function manifestPath(dir) {
|
|
17329
|
-
return (0,
|
|
17527
|
+
return (0, import_node_path22.join)(dir, "manifest.json");
|
|
17330
17528
|
}
|
|
17331
17529
|
function mirrorPath(dir, repoRelPath) {
|
|
17332
|
-
return (0,
|
|
17530
|
+
return (0, import_node_path22.join)(dir, "files", repoRelPath);
|
|
17333
17531
|
}
|
|
17334
17532
|
var CARRY_FILE = `${BASELINE_DIR}/.carry`;
|
|
17335
17533
|
var CARRY_WINDOW_MS = 12e4;
|
|
17336
17534
|
function writeCarry(sessionId, headSha) {
|
|
17337
17535
|
try {
|
|
17338
|
-
(0,
|
|
17339
|
-
(0,
|
|
17536
|
+
(0, import_node_fs24.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
|
|
17537
|
+
(0, import_node_fs24.writeFileSync)(
|
|
17340
17538
|
projectPath(CARRY_FILE),
|
|
17341
17539
|
JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
|
|
17342
17540
|
);
|
|
@@ -17346,10 +17544,10 @@ function writeCarry(sessionId, headSha) {
|
|
|
17346
17544
|
function claimCarry(newKey) {
|
|
17347
17545
|
const carryPath = projectPath(CARRY_FILE);
|
|
17348
17546
|
try {
|
|
17349
|
-
if (!(0,
|
|
17350
|
-
const carry = JSON.parse((0,
|
|
17547
|
+
if (!(0, import_node_fs24.existsSync)(carryPath)) return null;
|
|
17548
|
+
const carry = JSON.parse((0, import_node_fs24.readFileSync)(carryPath, "utf-8"));
|
|
17351
17549
|
try {
|
|
17352
|
-
(0,
|
|
17550
|
+
(0, import_node_fs24.rmSync)(carryPath, { force: true });
|
|
17353
17551
|
} catch {
|
|
17354
17552
|
}
|
|
17355
17553
|
if (!carry?.from_key || typeof carry.ts !== "number") return null;
|
|
@@ -17360,11 +17558,11 @@ function claimCarry(newKey) {
|
|
|
17360
17558
|
if (!prior) return null;
|
|
17361
17559
|
const toDir = sessionDir(newKey);
|
|
17362
17560
|
try {
|
|
17363
|
-
(0,
|
|
17561
|
+
(0, import_node_fs24.rmSync)(toDir, { recursive: true, force: true });
|
|
17364
17562
|
} catch {
|
|
17365
17563
|
}
|
|
17366
|
-
(0,
|
|
17367
|
-
(0,
|
|
17564
|
+
(0, import_node_fs24.renameSync)(fromDir, toDir);
|
|
17565
|
+
(0, import_node_fs24.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
|
|
17368
17566
|
return readManifest(toDir);
|
|
17369
17567
|
} catch {
|
|
17370
17568
|
return null;
|
|
@@ -17388,21 +17586,21 @@ function captureBaseline(opts = {}) {
|
|
|
17388
17586
|
const head_sha = getCurrentCommit();
|
|
17389
17587
|
const dirty = getDirtyFiles();
|
|
17390
17588
|
try {
|
|
17391
|
-
(0,
|
|
17589
|
+
(0, import_node_fs24.rmSync)(dir, { recursive: true, force: true });
|
|
17392
17590
|
} catch {
|
|
17393
17591
|
}
|
|
17394
|
-
const filesDir = (0,
|
|
17592
|
+
const filesDir = (0, import_node_path22.join)(dir, "files");
|
|
17395
17593
|
const mirrored = [];
|
|
17396
17594
|
try {
|
|
17397
|
-
(0,
|
|
17595
|
+
(0, import_node_fs24.mkdirSync)(filesDir, { recursive: true });
|
|
17398
17596
|
for (const p of dirty) {
|
|
17399
17597
|
if (p.includes("..")) continue;
|
|
17400
17598
|
const content = safeReadForMirror(projectPath(p));
|
|
17401
17599
|
if (content === null) continue;
|
|
17402
17600
|
const dest = mirrorPath(dir, p);
|
|
17403
17601
|
try {
|
|
17404
|
-
(0,
|
|
17405
|
-
(0,
|
|
17602
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path22.dirname)(dest), { recursive: true });
|
|
17603
|
+
(0, import_node_fs24.writeFileSync)(dest, content);
|
|
17406
17604
|
mirrored.push(p);
|
|
17407
17605
|
} catch {
|
|
17408
17606
|
}
|
|
@@ -17417,8 +17615,8 @@ function captureBaseline(opts = {}) {
|
|
|
17417
17615
|
version: BASELINE_VERSION
|
|
17418
17616
|
};
|
|
17419
17617
|
try {
|
|
17420
|
-
(0,
|
|
17421
|
-
(0,
|
|
17618
|
+
(0, import_node_fs24.mkdirSync)(dir, { recursive: true });
|
|
17619
|
+
(0, import_node_fs24.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
|
|
17422
17620
|
} catch {
|
|
17423
17621
|
}
|
|
17424
17622
|
pruneOldBaselines();
|
|
@@ -17429,9 +17627,9 @@ function readBaseline(sessionId) {
|
|
|
17429
17627
|
}
|
|
17430
17628
|
function readManifest(dir) {
|
|
17431
17629
|
const mp = manifestPath(dir);
|
|
17432
|
-
if (!(0,
|
|
17630
|
+
if (!(0, import_node_fs24.existsSync)(mp)) return null;
|
|
17433
17631
|
try {
|
|
17434
|
-
const parsed = JSON.parse((0,
|
|
17632
|
+
const parsed = JSON.parse((0, import_node_fs24.readFileSync)(mp, "utf-8"));
|
|
17435
17633
|
if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
|
|
17436
17634
|
return null;
|
|
17437
17635
|
}
|
|
@@ -17462,9 +17660,9 @@ function preImage(repoRelPath, baseline) {
|
|
|
17462
17660
|
function resolvePreImage(repoRelPath, baseline) {
|
|
17463
17661
|
if (baseline.dirty_paths.includes(repoRelPath)) {
|
|
17464
17662
|
const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
|
|
17465
|
-
if ((0,
|
|
17663
|
+
if ((0, import_node_fs24.existsSync)(mp)) {
|
|
17466
17664
|
try {
|
|
17467
|
-
return { content: (0,
|
|
17665
|
+
return { content: (0, import_node_fs24.readFileSync)(mp, "utf-8"), existed: true };
|
|
17468
17666
|
} catch {
|
|
17469
17667
|
}
|
|
17470
17668
|
}
|
|
@@ -17509,8 +17707,8 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
17509
17707
|
const content = safeReadForMirror(projectPath(p));
|
|
17510
17708
|
if (content === null) continue;
|
|
17511
17709
|
const dest = mirrorPath(dir, p);
|
|
17512
|
-
(0,
|
|
17513
|
-
(0,
|
|
17710
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path22.dirname)(dest), { recursive: true });
|
|
17711
|
+
(0, import_node_fs24.writeFileSync)(dest, content);
|
|
17514
17712
|
dirty.add(p);
|
|
17515
17713
|
adopted++;
|
|
17516
17714
|
} catch {
|
|
@@ -17519,7 +17717,7 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
17519
17717
|
if (adopted === 0) return 0;
|
|
17520
17718
|
try {
|
|
17521
17719
|
const updated = { ...baseline, dirty_paths: [...dirty] };
|
|
17522
|
-
(0,
|
|
17720
|
+
(0, import_node_fs24.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
|
|
17523
17721
|
preImageCache.delete(baseline);
|
|
17524
17722
|
} catch {
|
|
17525
17723
|
return 0;
|
|
@@ -17530,7 +17728,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
17530
17728
|
const pre = preImage(repoRelPath, baseline);
|
|
17531
17729
|
let current;
|
|
17532
17730
|
try {
|
|
17533
|
-
current = (0,
|
|
17731
|
+
current = (0, import_node_fs24.readFileSync)(projectPath(repoRelPath), "utf-8");
|
|
17534
17732
|
} catch {
|
|
17535
17733
|
return pre.existed;
|
|
17536
17734
|
}
|
|
@@ -17539,8 +17737,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
17539
17737
|
}
|
|
17540
17738
|
function safeReadForMirror(absPath) {
|
|
17541
17739
|
try {
|
|
17542
|
-
if ((0,
|
|
17543
|
-
const buf = (0,
|
|
17740
|
+
if ((0, import_node_fs24.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
|
|
17741
|
+
const buf = (0, import_node_fs24.readFileSync)(absPath);
|
|
17544
17742
|
if (buf.includes(0)) return null;
|
|
17545
17743
|
return buf.toString("utf-8");
|
|
17546
17744
|
} catch {
|
|
@@ -17551,18 +17749,18 @@ function pruneOldBaselines() {
|
|
|
17551
17749
|
const root = projectPath(BASELINE_DIR);
|
|
17552
17750
|
let entries;
|
|
17553
17751
|
try {
|
|
17554
|
-
entries = (0,
|
|
17752
|
+
entries = (0, import_node_fs24.readdirSync)(root);
|
|
17555
17753
|
} catch {
|
|
17556
17754
|
return;
|
|
17557
17755
|
}
|
|
17558
17756
|
const now = Date.now();
|
|
17559
17757
|
for (const name of entries) {
|
|
17560
|
-
const dir = (0,
|
|
17758
|
+
const dir = (0, import_node_path22.join)(root, name);
|
|
17561
17759
|
const manifest = readManifest(dir);
|
|
17562
17760
|
if (!manifest) {
|
|
17563
17761
|
try {
|
|
17564
|
-
if (now - (0,
|
|
17565
|
-
(0,
|
|
17762
|
+
if (now - (0, import_node_fs24.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
|
|
17763
|
+
(0, import_node_fs24.rmSync)(dir, { recursive: true, force: true });
|
|
17566
17764
|
}
|
|
17567
17765
|
} catch {
|
|
17568
17766
|
}
|
|
@@ -17570,7 +17768,7 @@ function pruneOldBaselines() {
|
|
|
17570
17768
|
}
|
|
17571
17769
|
if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
|
|
17572
17770
|
try {
|
|
17573
|
-
(0,
|
|
17771
|
+
(0, import_node_fs24.rmSync)(dir, { recursive: true, force: true });
|
|
17574
17772
|
} catch {
|
|
17575
17773
|
}
|
|
17576
17774
|
}
|
|
@@ -17745,8 +17943,8 @@ function buildCompactionContext(session) {
|
|
|
17745
17943
|
commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
|
|
17746
17944
|
readFileLines: (file) => {
|
|
17747
17945
|
try {
|
|
17748
|
-
const abs = (0,
|
|
17749
|
-
return (0,
|
|
17946
|
+
const abs = (0, import_node_path23.join)(root, file);
|
|
17947
|
+
return (0, import_node_fs25.existsSync)(abs) ? (0, import_node_fs25.readFileSync)(abs, "utf8").split("\n") : null;
|
|
17750
17948
|
} catch {
|
|
17751
17949
|
return null;
|
|
17752
17950
|
}
|
|
@@ -17803,24 +18001,24 @@ async function readHookStdin() {
|
|
|
17803
18001
|
|
|
17804
18002
|
// src/commands/standard.ts
|
|
17805
18003
|
var import_promises13 = require("node:fs/promises");
|
|
17806
|
-
var
|
|
18004
|
+
var import_node_fs32 = require("node:fs");
|
|
17807
18005
|
var import_yaml3 = __toESM(require_dist());
|
|
17808
18006
|
|
|
17809
18007
|
// src/lib/synthesize.ts
|
|
17810
18008
|
var import_node_child_process9 = require("node:child_process");
|
|
17811
|
-
var
|
|
18009
|
+
var import_node_fs28 = require("node:fs");
|
|
17812
18010
|
var import_promises10 = require("node:fs/promises");
|
|
17813
|
-
var
|
|
18011
|
+
var import_node_path26 = require("node:path");
|
|
17814
18012
|
var import_yaml = __toESM(require_dist());
|
|
17815
18013
|
|
|
17816
18014
|
// src/lib/data-dir.ts
|
|
17817
|
-
var
|
|
17818
|
-
var
|
|
18015
|
+
var import_node_fs26 = require("node:fs");
|
|
18016
|
+
var import_node_path24 = require("node:path");
|
|
17819
18017
|
function resolveDataDir() {
|
|
17820
18018
|
const candidates2 = [
|
|
17821
|
-
(0,
|
|
18019
|
+
(0, import_node_path24.join)(__dirname, "..", "data"),
|
|
17822
18020
|
// installed: node_modules/@codacy/verity-cli/data
|
|
17823
|
-
(0,
|
|
18021
|
+
(0, import_node_path24.join)(__dirname, "..", "..", "data"),
|
|
17824
18022
|
// edge case: nested resolution
|
|
17825
18023
|
// THE COMMITTED SOURCE, for a source checkout that has not been built.
|
|
17826
18024
|
// cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
|
|
@@ -17829,14 +18027,14 @@ function resolveDataDir() {
|
|
|
17829
18027
|
// without this the synthesizer throws "Could not find Verity skill data"
|
|
17830
18028
|
// for every test and every `verity` run from source. Resolved from this
|
|
17831
18029
|
// module's own location, never the cwd: see the warning below.
|
|
17832
|
-
(0,
|
|
18030
|
+
(0, import_node_path24.join)(__dirname, "..", "..", "client"),
|
|
17833
18031
|
// bundled: cli/bin/ → ../../client
|
|
17834
|
-
(0,
|
|
18032
|
+
(0, import_node_path24.join)(__dirname, "..", "..", "..", "client"),
|
|
17835
18033
|
// tsx: cli/src/lib/ → ../../../client
|
|
17836
18034
|
...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
|
|
17837
18035
|
];
|
|
17838
18036
|
for (const candidate of candidates2) {
|
|
17839
|
-
if ((0,
|
|
18037
|
+
if ((0, import_node_fs26.existsSync)((0, import_node_path24.join)(candidate, "skills"))) {
|
|
17840
18038
|
return candidate;
|
|
17841
18039
|
}
|
|
17842
18040
|
}
|
|
@@ -17845,13 +18043,13 @@ function resolveDataDir() {
|
|
|
17845
18043
|
);
|
|
17846
18044
|
}
|
|
17847
18045
|
function setupDataPath(file) {
|
|
17848
|
-
return (0,
|
|
18046
|
+
return (0, import_node_path24.join)(resolveDataDir(), "skills", "verity-setup", file);
|
|
17849
18047
|
}
|
|
17850
18048
|
|
|
17851
18049
|
// src/lib/detect.ts
|
|
17852
18050
|
var import_node_child_process8 = require("node:child_process");
|
|
17853
|
-
var
|
|
17854
|
-
var
|
|
18051
|
+
var import_node_fs27 = require("node:fs");
|
|
18052
|
+
var import_node_path25 = require("node:path");
|
|
17855
18053
|
var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
17856
18054
|
"typescript",
|
|
17857
18055
|
"javascript",
|
|
@@ -17908,25 +18106,25 @@ function walk(root) {
|
|
|
17908
18106
|
if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
|
|
17909
18107
|
let entries;
|
|
17910
18108
|
try {
|
|
17911
|
-
entries = (0,
|
|
18109
|
+
entries = (0, import_node_fs27.readdirSync)(dir, { withFileTypes: true });
|
|
17912
18110
|
} catch {
|
|
17913
18111
|
return;
|
|
17914
18112
|
}
|
|
17915
18113
|
for (const entry of entries) {
|
|
17916
18114
|
if (found.length >= WALK_MAX_FILES) return;
|
|
17917
18115
|
if (IGNORED_SEGMENTS.includes(entry.name)) continue;
|
|
17918
|
-
const full = (0,
|
|
18116
|
+
const full = (0, import_node_path25.join)(dir, entry.name);
|
|
17919
18117
|
if (entry.isDirectory()) visit(full, depth + 1);
|
|
17920
|
-
else if (entry.isFile()) found.push((0,
|
|
18118
|
+
else if (entry.isFile()) found.push((0, import_node_path25.relative)(root, full));
|
|
17921
18119
|
}
|
|
17922
18120
|
};
|
|
17923
18121
|
visit(root, 0);
|
|
17924
18122
|
return found;
|
|
17925
18123
|
}
|
|
17926
18124
|
function languageOf(path) {
|
|
17927
|
-
const name = (0,
|
|
18125
|
+
const name = (0, import_node_path25.basename)(path);
|
|
17928
18126
|
if (/^Dockerfile(\..+)?$/i.test(name)) return "dockerfile";
|
|
17929
|
-
if (!(0,
|
|
18127
|
+
if (!(0, import_node_path25.extname)(name)) return null;
|
|
17930
18128
|
const lang = detectLanguage(path);
|
|
17931
18129
|
return lang || null;
|
|
17932
18130
|
}
|
|
@@ -17981,9 +18179,9 @@ var TOOL_CONFIG_MARKERS = [
|
|
|
17981
18179
|
["detekt", ["detekt.yml", "detekt.yaml"]],
|
|
17982
18180
|
["Hadolint", [".hadolint.yaml", ".hadolint.yml"]]
|
|
17983
18181
|
];
|
|
17984
|
-
function
|
|
18182
|
+
function readJson2(path) {
|
|
17985
18183
|
try {
|
|
17986
|
-
return JSON.parse((0,
|
|
18184
|
+
return JSON.parse((0, import_node_fs27.readFileSync)(path, "utf-8"));
|
|
17987
18185
|
} catch {
|
|
17988
18186
|
return null;
|
|
17989
18187
|
}
|
|
@@ -18001,24 +18199,24 @@ var NESTED_MANIFEST_LIMIT = 25;
|
|
|
18001
18199
|
function declaredDependencies(root, files) {
|
|
18002
18200
|
const names2 = [];
|
|
18003
18201
|
const readPackageJson = (path) => {
|
|
18004
|
-
const pkg =
|
|
18202
|
+
const pkg = readJson2(path);
|
|
18005
18203
|
if (!pkg) return;
|
|
18006
18204
|
for (const field of ["dependencies", "devDependencies", "peerDependencies"]) {
|
|
18007
18205
|
const deps = pkg[field];
|
|
18008
18206
|
if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
|
|
18009
18207
|
}
|
|
18010
18208
|
};
|
|
18011
|
-
readPackageJson((0,
|
|
18012
|
-
const nested = files.filter((f) => f.includes("/") && (0,
|
|
18013
|
-
for (const rel of nested) readPackageJson((0,
|
|
18209
|
+
readPackageJson((0, import_node_path25.join)(root, "package.json"));
|
|
18210
|
+
const nested = files.filter((f) => f.includes("/") && (0, import_node_path25.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
|
|
18211
|
+
for (const rel of nested) readPackageJson((0, import_node_path25.join)(root, rel));
|
|
18014
18212
|
const pythonManifests = [
|
|
18015
|
-
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0,
|
|
18016
|
-
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0,
|
|
18213
|
+
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path25.join)(root, f)),
|
|
18214
|
+
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path25.join)(root, f))
|
|
18017
18215
|
];
|
|
18018
18216
|
for (const path of pythonManifests) {
|
|
18019
|
-
if (!(0,
|
|
18217
|
+
if (!(0, import_node_fs27.existsSync)(path)) continue;
|
|
18020
18218
|
try {
|
|
18021
|
-
const text = (0,
|
|
18219
|
+
const text = (0, import_node_fs27.readFileSync)(path, "utf-8");
|
|
18022
18220
|
for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
|
|
18023
18221
|
for (const line of text.split("\n")) {
|
|
18024
18222
|
if (!/dependencies\s*=/.test(line)) continue;
|
|
@@ -18028,13 +18226,13 @@ function declaredDependencies(root, files) {
|
|
|
18028
18226
|
}
|
|
18029
18227
|
}
|
|
18030
18228
|
const goMods = [
|
|
18031
|
-
(0,
|
|
18032
|
-
...files.filter((f) => f.includes("/") && (0,
|
|
18229
|
+
(0, import_node_path25.join)(root, "go.mod"),
|
|
18230
|
+
...files.filter((f) => f.includes("/") && (0, import_node_path25.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path25.join)(root, f))
|
|
18033
18231
|
];
|
|
18034
18232
|
for (const path of goMods) {
|
|
18035
|
-
if (!(0,
|
|
18233
|
+
if (!(0, import_node_fs27.existsSync)(path)) continue;
|
|
18036
18234
|
try {
|
|
18037
|
-
const text = (0,
|
|
18235
|
+
const text = (0, import_node_fs27.readFileSync)(path, "utf-8");
|
|
18038
18236
|
for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
|
|
18039
18237
|
names2.push(m[1].replace(/^github\.com\//, ""));
|
|
18040
18238
|
}
|
|
@@ -18042,10 +18240,10 @@ function declaredDependencies(root, files) {
|
|
|
18042
18240
|
}
|
|
18043
18241
|
}
|
|
18044
18242
|
for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
|
|
18045
|
-
const path = (0,
|
|
18046
|
-
if (!(0,
|
|
18243
|
+
const path = (0, import_node_path25.join)(root, file);
|
|
18244
|
+
if (!(0, import_node_fs27.existsSync)(path)) continue;
|
|
18047
18245
|
try {
|
|
18048
|
-
const text = (0,
|
|
18246
|
+
const text = (0, import_node_fs27.readFileSync)(path, "utf-8");
|
|
18049
18247
|
for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
|
|
18050
18248
|
} catch {
|
|
18051
18249
|
}
|
|
@@ -18053,7 +18251,7 @@ function declaredDependencies(root, files) {
|
|
|
18053
18251
|
return names2;
|
|
18054
18252
|
}
|
|
18055
18253
|
function detectBuildSystem(root, files) {
|
|
18056
|
-
const has = (f) => (0,
|
|
18254
|
+
const has = (f) => (0, import_node_fs27.existsSync)((0, import_node_path25.join)(root, f)) || files.some((p) => (0, import_node_path25.basename)(p) === f);
|
|
18057
18255
|
if (has("pnpm-lock.yaml")) return "pnpm";
|
|
18058
18256
|
if (has("yarn.lock")) return "yarn";
|
|
18059
18257
|
if (has("bun.lock") || has("bun.lockb")) return "bun";
|
|
@@ -18070,8 +18268,8 @@ function detectBuildSystem(root, files) {
|
|
|
18070
18268
|
}
|
|
18071
18269
|
function detectArchitecture(root, files) {
|
|
18072
18270
|
const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
|
|
18073
|
-
if (workspaceMarkers.some((m) => (0,
|
|
18074
|
-
const pkg =
|
|
18271
|
+
if (workspaceMarkers.some((m) => (0, import_node_fs27.existsSync)((0, import_node_path25.join)(root, m)))) return "monorepo";
|
|
18272
|
+
const pkg = readJson2((0, import_node_path25.join)(root, "package.json"));
|
|
18075
18273
|
if (pkg && "workspaces" in pkg) return "monorepo";
|
|
18076
18274
|
const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
|
|
18077
18275
|
const nested = manifests.filter((f) => f.includes("/"));
|
|
@@ -18093,10 +18291,10 @@ function measureAvgFileLength(root, files, languages) {
|
|
|
18093
18291
|
let total = 0;
|
|
18094
18292
|
let counted = 0;
|
|
18095
18293
|
for (let i = 0; i < candidates2.length; i += stride) {
|
|
18096
|
-
const path = (0,
|
|
18294
|
+
const path = (0, import_node_path25.join)(root, candidates2[i]);
|
|
18097
18295
|
try {
|
|
18098
|
-
if ((0,
|
|
18099
|
-
total += (0,
|
|
18296
|
+
if ((0, import_node_fs27.statSync)(path).size > 2 * 1024 * 1024) continue;
|
|
18297
|
+
total += (0, import_node_fs27.readFileSync)(path, "utf-8").split("\n").length;
|
|
18100
18298
|
counted++;
|
|
18101
18299
|
} catch {
|
|
18102
18300
|
}
|
|
@@ -18126,14 +18324,14 @@ function detectProject(root = repoRoot()) {
|
|
|
18126
18324
|
const existingToolConfigs = [];
|
|
18127
18325
|
for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
|
|
18128
18326
|
for (const marker of markers) {
|
|
18129
|
-
if ((0,
|
|
18327
|
+
if ((0, import_node_fs27.existsSync)((0, import_node_path25.join)(root, marker))) {
|
|
18130
18328
|
existingToolConfigs.push({ tool, path: `./${marker}` });
|
|
18131
18329
|
break;
|
|
18132
18330
|
}
|
|
18133
18331
|
}
|
|
18134
18332
|
}
|
|
18135
18333
|
return {
|
|
18136
|
-
projectName: (0,
|
|
18334
|
+
projectName: (0, import_node_path25.basename)(root),
|
|
18137
18335
|
languages,
|
|
18138
18336
|
languageCounts,
|
|
18139
18337
|
frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
|
|
@@ -18231,8 +18429,8 @@ ${closingNote(input.origin)}
|
|
|
18231
18429
|
|
|
18232
18430
|
// src/lib/synthesize.ts
|
|
18233
18431
|
function loadCatalog() {
|
|
18234
|
-
const catalog = (0, import_yaml.parse)((0,
|
|
18235
|
-
const template = (0, import_yaml.parse)((0,
|
|
18432
|
+
const catalog = (0, import_yaml.parse)((0, import_node_fs28.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
|
|
18433
|
+
const template = (0, import_yaml.parse)((0, import_node_fs28.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
|
|
18236
18434
|
return { catalog, template };
|
|
18237
18435
|
}
|
|
18238
18436
|
function selectTools(languages, intensity, catalog) {
|
|
@@ -18510,7 +18708,7 @@ function validatePatternIds() {
|
|
|
18510
18708
|
}
|
|
18511
18709
|
async function runSynthesis(opts) {
|
|
18512
18710
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18513
|
-
if ((0,
|
|
18711
|
+
if ((0, import_node_fs28.existsSync)(standardPath) && !opts.force) {
|
|
18514
18712
|
return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
|
|
18515
18713
|
}
|
|
18516
18714
|
const detected = opts.detected ?? detectProject();
|
|
@@ -18577,9 +18775,9 @@ async function correctVerityMdVersion(opts) {
|
|
|
18577
18775
|
origin: { kind: "synthesized", tools: opts.tools }
|
|
18578
18776
|
}));
|
|
18579
18777
|
}
|
|
18580
|
-
async function writeFileTo(
|
|
18581
|
-
const target = projectPath(
|
|
18582
|
-
await (0, import_promises10.mkdir)((0,
|
|
18778
|
+
async function writeFileTo(relative3, body) {
|
|
18779
|
+
const target = projectPath(relative3);
|
|
18780
|
+
await (0, import_promises10.mkdir)((0, import_node_path26.dirname)(target), { recursive: true });
|
|
18583
18781
|
await (0, import_promises10.writeFile)(target, body);
|
|
18584
18782
|
}
|
|
18585
18783
|
async function deriveConfigForStandard(standard) {
|
|
@@ -18638,11 +18836,11 @@ ${validation.detail}`);
|
|
|
18638
18836
|
|
|
18639
18837
|
// src/lib/setup-state.ts
|
|
18640
18838
|
var import_promises11 = require("node:fs/promises");
|
|
18641
|
-
var
|
|
18839
|
+
var import_node_fs29 = require("node:fs");
|
|
18642
18840
|
var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
|
|
18643
18841
|
async function readSetupState() {
|
|
18644
18842
|
const path = projectPath(SETUP_STATE_FILE);
|
|
18645
|
-
if (!(0,
|
|
18843
|
+
if (!(0, import_node_fs29.existsSync)(path)) return null;
|
|
18646
18844
|
try {
|
|
18647
18845
|
const parsed = JSON.parse(await (0, import_promises11.readFile)(path, "utf-8"));
|
|
18648
18846
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
@@ -18658,12 +18856,12 @@ async function writeSetupState(patch) {
|
|
|
18658
18856
|
}
|
|
18659
18857
|
|
|
18660
18858
|
// src/lib/push-setup.ts
|
|
18661
|
-
var
|
|
18859
|
+
var import_node_fs31 = require("node:fs");
|
|
18662
18860
|
var import_promises12 = require("node:fs/promises");
|
|
18663
18861
|
var import_yaml2 = __toESM(require_dist());
|
|
18664
18862
|
|
|
18665
18863
|
// src/lib/verityignore.ts
|
|
18666
|
-
var
|
|
18864
|
+
var import_node_fs30 = require("node:fs");
|
|
18667
18865
|
var EMPTY = { rules: [], securityOverlap: [], problems: [] };
|
|
18668
18866
|
var SECURITY_PROBES = [
|
|
18669
18867
|
".env",
|
|
@@ -18756,9 +18954,9 @@ function isIgnored3(ig, path) {
|
|
|
18756
18954
|
}
|
|
18757
18955
|
function loadVerityIgnore() {
|
|
18758
18956
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
18759
|
-
if (!(0,
|
|
18957
|
+
if (!(0, import_node_fs30.existsSync)(file)) return EMPTY;
|
|
18760
18958
|
try {
|
|
18761
|
-
return parseVerityIgnore((0,
|
|
18959
|
+
return parseVerityIgnore((0, import_node_fs30.readFileSync)(file, "utf-8"));
|
|
18762
18960
|
} catch {
|
|
18763
18961
|
return EMPTY;
|
|
18764
18962
|
}
|
|
@@ -18796,9 +18994,9 @@ function buildStandardUpload(standard, ignoreRaw) {
|
|
|
18796
18994
|
}
|
|
18797
18995
|
function readVerityIgnoreRaw() {
|
|
18798
18996
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
18799
|
-
if (!(0,
|
|
18997
|
+
if (!(0, import_node_fs30.existsSync)(file)) return null;
|
|
18800
18998
|
try {
|
|
18801
|
-
return (0,
|
|
18999
|
+
return (0, import_node_fs30.readFileSync)(file, "utf-8");
|
|
18802
19000
|
} catch {
|
|
18803
19001
|
return null;
|
|
18804
19002
|
}
|
|
@@ -18826,7 +19024,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
18826
19024
|
}
|
|
18827
19025
|
let standardVersion = null;
|
|
18828
19026
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18829
|
-
if (pushStandard && (0,
|
|
19027
|
+
if (pushStandard && (0, import_node_fs31.existsSync)(standardPath)) {
|
|
18830
19028
|
try {
|
|
18831
19029
|
const content = (0, import_yaml2.parse)(await (0, import_promises12.readFile)(standardPath, "utf-8"));
|
|
18832
19030
|
const upload = buildStandardUpload(content, readVerityIgnoreRaw());
|
|
@@ -18851,7 +19049,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
18851
19049
|
}
|
|
18852
19050
|
let configPushed = false;
|
|
18853
19051
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
18854
|
-
if (pushConfig && (0,
|
|
19052
|
+
if (pushConfig && (0, import_node_fs31.existsSync)(configPath)) {
|
|
18855
19053
|
try {
|
|
18856
19054
|
const content = JSON.parse(await (0, import_promises12.readFile)(configPath, "utf-8"));
|
|
18857
19055
|
const result = await apiRequest({
|
|
@@ -18883,7 +19081,7 @@ function registerStandardCommands(program2) {
|
|
|
18883
19081
|
const state = await readSetupState();
|
|
18884
19082
|
if (opts.configOnly) {
|
|
18885
19083
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18886
|
-
if (!(0,
|
|
19084
|
+
if (!(0, import_node_fs32.existsSync)(standardPath)) {
|
|
18887
19085
|
printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
|
|
18888
19086
|
process.exit(1);
|
|
18889
19087
|
}
|
|
@@ -19195,7 +19393,9 @@ function formatRunDetail(run2) {
|
|
|
19195
19393
|
if (f.description && f.description !== title) lines.push(` ${f.description}`);
|
|
19196
19394
|
const fix = f.fix?.description ?? f.suggestion;
|
|
19197
19395
|
if (fix) lines.push(` \u21B3 fix: ${fix}`);
|
|
19198
|
-
if (f.scope === "pre-existing")
|
|
19396
|
+
if (f.scope === "pre-existing") {
|
|
19397
|
+
lines.push(f.provenance === "caused-elsewhere" ? " (caused elsewhere \u2014 not by this change)" : " (pre-existing)");
|
|
19398
|
+
}
|
|
19199
19399
|
}
|
|
19200
19400
|
}
|
|
19201
19401
|
const pending = run2.pending_items ?? [];
|
|
@@ -19214,10 +19414,10 @@ function formatRunDetail(run2) {
|
|
|
19214
19414
|
}
|
|
19215
19415
|
|
|
19216
19416
|
// src/lib/ignore-declaration.ts
|
|
19217
|
-
var
|
|
19417
|
+
var import_node_fs34 = require("node:fs");
|
|
19218
19418
|
|
|
19219
19419
|
// src/lib/debounce.ts
|
|
19220
|
-
var
|
|
19420
|
+
var import_node_fs33 = require("node:fs");
|
|
19221
19421
|
var import_node_crypto10 = require("node:crypto");
|
|
19222
19422
|
function scopedFile(base, sessionId) {
|
|
19223
19423
|
if (!sessionId) return base;
|
|
@@ -19225,9 +19425,9 @@ function scopedFile(base, sessionId) {
|
|
|
19225
19425
|
}
|
|
19226
19426
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
19227
19427
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19228
|
-
if (!(0,
|
|
19428
|
+
if (!(0, import_node_fs33.existsSync)(file)) return null;
|
|
19229
19429
|
try {
|
|
19230
|
-
const lastTs = parseInt((0,
|
|
19430
|
+
const lastTs = parseInt((0, import_node_fs33.readFileSync)(file, "utf-8").trim(), 10);
|
|
19231
19431
|
const nowTs = Math.floor(Date.now() / 1e3);
|
|
19232
19432
|
const elapsed = nowTs - lastTs;
|
|
19233
19433
|
if (elapsed < debounceSeconds) {
|
|
@@ -19240,10 +19440,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
|
19240
19440
|
function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
19241
19441
|
if (bypassForRecentCommits) return null;
|
|
19242
19442
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19243
|
-
if (!(0,
|
|
19443
|
+
if (!(0, import_node_fs33.existsSync)(file)) return null;
|
|
19244
19444
|
let debounceTime;
|
|
19245
19445
|
try {
|
|
19246
|
-
debounceTime = (0,
|
|
19446
|
+
debounceTime = (0, import_node_fs33.statSync)(file).mtimeMs;
|
|
19247
19447
|
} catch {
|
|
19248
19448
|
return null;
|
|
19249
19449
|
}
|
|
@@ -19251,7 +19451,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
19251
19451
|
const resolved = resolveFile(f);
|
|
19252
19452
|
if (!resolved) continue;
|
|
19253
19453
|
try {
|
|
19254
|
-
const stat3 = (0,
|
|
19454
|
+
const stat3 = (0, import_node_fs33.statSync)(resolved);
|
|
19255
19455
|
if (stat3.mtimeMs > debounceTime) {
|
|
19256
19456
|
return null;
|
|
19257
19457
|
}
|
|
@@ -19267,8 +19467,8 @@ function computeContentHash(files) {
|
|
|
19267
19467
|
for (const f of sorted) {
|
|
19268
19468
|
const resolved = resolveFile(f) ?? f;
|
|
19269
19469
|
try {
|
|
19270
|
-
if ((0,
|
|
19271
|
-
hash.update((0,
|
|
19470
|
+
if ((0, import_node_fs33.existsSync)(resolved)) {
|
|
19471
|
+
hash.update((0, import_node_fs33.readFileSync)(resolved));
|
|
19272
19472
|
}
|
|
19273
19473
|
} catch {
|
|
19274
19474
|
}
|
|
@@ -19278,9 +19478,9 @@ function computeContentHash(files) {
|
|
|
19278
19478
|
function checkContentHash(files, sessionId) {
|
|
19279
19479
|
const hash = computeContentHash(files);
|
|
19280
19480
|
const file = scopedFile(HASH_FILE, sessionId);
|
|
19281
|
-
if ((0,
|
|
19481
|
+
if ((0, import_node_fs33.existsSync)(file)) {
|
|
19282
19482
|
try {
|
|
19283
|
-
const storedHash = (0,
|
|
19483
|
+
const storedHash = (0, import_node_fs33.readFileSync)(file, "utf-8").trim();
|
|
19284
19484
|
if (hash === storedHash) {
|
|
19285
19485
|
return { skip: "No source changes since last analysis", hash };
|
|
19286
19486
|
}
|
|
@@ -19290,24 +19490,24 @@ function checkContentHash(files, sessionId) {
|
|
|
19290
19490
|
return { skip: null, hash };
|
|
19291
19491
|
}
|
|
19292
19492
|
function recordAnalysisStart(sessionId) {
|
|
19293
|
-
(0,
|
|
19294
|
-
(0,
|
|
19493
|
+
(0, import_node_fs33.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
19494
|
+
(0, import_node_fs33.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
|
|
19295
19495
|
}
|
|
19296
19496
|
function recordPassHash(hash, sessionId) {
|
|
19297
|
-
(0,
|
|
19497
|
+
(0, import_node_fs33.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
|
|
19298
19498
|
}
|
|
19299
19499
|
function narrowToRecent(files, sessionId) {
|
|
19300
19500
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19301
|
-
if (!(0,
|
|
19501
|
+
if (!(0, import_node_fs33.existsSync)(file)) return files;
|
|
19302
19502
|
let debounceTime;
|
|
19303
19503
|
try {
|
|
19304
|
-
debounceTime = (0,
|
|
19504
|
+
debounceTime = (0, import_node_fs33.statSync)(file).mtimeMs;
|
|
19305
19505
|
} catch {
|
|
19306
19506
|
return files;
|
|
19307
19507
|
}
|
|
19308
19508
|
const recent = files.filter((f) => {
|
|
19309
19509
|
try {
|
|
19310
|
-
return (0,
|
|
19510
|
+
return (0, import_node_fs33.existsSync)(f) && (0, import_node_fs33.statSync)(f).mtimeMs > debounceTime;
|
|
19311
19511
|
} catch {
|
|
19312
19512
|
return false;
|
|
19313
19513
|
}
|
|
@@ -19320,9 +19520,9 @@ function readIteration(currentCommit, _contentHash) {
|
|
|
19320
19520
|
var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
|
|
19321
19521
|
function readBlockState(currentCommit, opts) {
|
|
19322
19522
|
if (opts?.newUserPrompt) return NO_BLOCKS;
|
|
19323
|
-
if (!(0,
|
|
19523
|
+
if (!(0, import_node_fs33.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
|
|
19324
19524
|
try {
|
|
19325
|
-
const stored = (0,
|
|
19525
|
+
const stored = (0, import_node_fs33.readFileSync)(ITERATION_FILE, "utf-8").trim();
|
|
19326
19526
|
const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
|
|
19327
19527
|
if (!parsed) return NO_BLOCKS;
|
|
19328
19528
|
if (parsed.commit !== currentCommit) return NO_BLOCKS;
|
|
@@ -19368,8 +19568,8 @@ function isSameProblem(previous, current) {
|
|
|
19368
19568
|
return current.split(",").some((k) => prev.has(k));
|
|
19369
19569
|
}
|
|
19370
19570
|
function writeBlockState(commit, state) {
|
|
19371
|
-
(0,
|
|
19372
|
-
(0,
|
|
19571
|
+
(0, import_node_fs33.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
19572
|
+
(0, import_node_fs33.writeFileSync)(
|
|
19373
19573
|
ITERATION_FILE,
|
|
19374
19574
|
JSON.stringify({
|
|
19375
19575
|
v: 2,
|
|
@@ -19474,9 +19674,9 @@ function resolveIgnoreState(keys) {
|
|
|
19474
19674
|
}
|
|
19475
19675
|
function readIgnoreState(sessionId) {
|
|
19476
19676
|
const file = stateFile(sessionId);
|
|
19477
|
-
if (!(0,
|
|
19677
|
+
if (!(0, import_node_fs34.existsSync)(file)) return null;
|
|
19478
19678
|
try {
|
|
19479
|
-
const o = JSON.parse((0,
|
|
19679
|
+
const o = JSON.parse((0, import_node_fs34.readFileSync)(file, "utf-8")) ?? {};
|
|
19480
19680
|
const spent = typeof o.spent === "number" ? o.spent : 0;
|
|
19481
19681
|
const raw = o.active;
|
|
19482
19682
|
let active = null;
|
|
@@ -19500,8 +19700,8 @@ function readIgnoreState(sessionId) {
|
|
|
19500
19700
|
}
|
|
19501
19701
|
function writeIgnoreState(state, sessionId) {
|
|
19502
19702
|
try {
|
|
19503
|
-
(0,
|
|
19504
|
-
(0,
|
|
19703
|
+
(0, import_node_fs34.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
19704
|
+
(0, import_node_fs34.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
|
|
19505
19705
|
} catch {
|
|
19506
19706
|
}
|
|
19507
19707
|
}
|
|
@@ -19884,15 +20084,15 @@ function createRun(opts, globals) {
|
|
|
19884
20084
|
}
|
|
19885
20085
|
|
|
19886
20086
|
// src/commands/analyze/index.ts
|
|
19887
|
-
var
|
|
20087
|
+
var import_node_fs47 = require("node:fs");
|
|
19888
20088
|
|
|
19889
20089
|
// src/lib/repo-context.ts
|
|
19890
20090
|
var import_node_child_process10 = require("node:child_process");
|
|
19891
|
-
var
|
|
20091
|
+
var import_node_os5 = require("node:os");
|
|
19892
20092
|
function rgInvocations(env = process.env) {
|
|
19893
20093
|
const out = [{ cmd: "rg" }];
|
|
19894
20094
|
if (env.CLAUDE_CODE_EXECPATH) out.push({ cmd: env.CLAUDE_CODE_EXECPATH, argv0: "rg" });
|
|
19895
|
-
out.push({ cmd: `${(0,
|
|
20095
|
+
out.push({ cmd: `${(0, import_node_os5.homedir)()}/.local/bin/claude`, argv0: "rg" });
|
|
19896
20096
|
return out;
|
|
19897
20097
|
}
|
|
19898
20098
|
function ripgrepEnv(base = process.env) {
|
|
@@ -20395,6 +20595,112 @@ function partitionSites(rgLines, symbols, opts) {
|
|
|
20395
20595
|
while (callers.length + tests.length > MAX_SITES) callers.pop();
|
|
20396
20596
|
return { callers, tests, dropped };
|
|
20397
20597
|
}
|
|
20598
|
+
var MAX_IMPORTERS = 12;
|
|
20599
|
+
var MAX_IMPORTERS_PER_FILE = 2;
|
|
20600
|
+
function moduleKey(path) {
|
|
20601
|
+
return path.replace(/\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/i, "").replace(/\/index$/, "");
|
|
20602
|
+
}
|
|
20603
|
+
function importSpecifier(text) {
|
|
20604
|
+
const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(text);
|
|
20605
|
+
return m?.[1] ?? null;
|
|
20606
|
+
}
|
|
20607
|
+
function resolveSpecifier(fromFile, spec) {
|
|
20608
|
+
if (!spec.startsWith(".")) return null;
|
|
20609
|
+
const dir = fromFile.includes("/") ? fromFile.slice(0, fromFile.lastIndexOf("/")) : "";
|
|
20610
|
+
const out = [];
|
|
20611
|
+
for (const part of (dir ? dir.split("/") : []).concat(spec.split("/"))) {
|
|
20612
|
+
if (part === "" || part === ".") continue;
|
|
20613
|
+
if (part === "..") {
|
|
20614
|
+
if (out.length === 0) return null;
|
|
20615
|
+
out.pop();
|
|
20616
|
+
continue;
|
|
20617
|
+
}
|
|
20618
|
+
out.push(part);
|
|
20619
|
+
}
|
|
20620
|
+
return out.length > 0 ? moduleKey(out.join("/")) : null;
|
|
20621
|
+
}
|
|
20622
|
+
function partitionImporters(rgLines, changedPaths, opts) {
|
|
20623
|
+
const changedByKey = /* @__PURE__ */ new Map();
|
|
20624
|
+
for (const p of changedPaths) changedByKey.set(moduleKey(p), p);
|
|
20625
|
+
const hits = rgLines.map(parseRgLine).filter((h) => h !== null);
|
|
20626
|
+
hits.sort((a, b) => a.file < b.file ? -1 : a.file > b.file ? 1 : a.line - b.line);
|
|
20627
|
+
const perFile = /* @__PURE__ */ new Map();
|
|
20628
|
+
const out = [];
|
|
20629
|
+
for (const h of hits) {
|
|
20630
|
+
if (out.length >= MAX_IMPORTERS) break;
|
|
20631
|
+
if (opts.sentPaths.has(h.file)) continue;
|
|
20632
|
+
if (opts.isExcluded(h.file)) continue;
|
|
20633
|
+
if (!isCodeSiteFile(h.file)) continue;
|
|
20634
|
+
const spec = importSpecifier(h.text);
|
|
20635
|
+
if (!spec) continue;
|
|
20636
|
+
const resolved = resolveSpecifier(h.file, spec);
|
|
20637
|
+
if (!resolved) continue;
|
|
20638
|
+
const changed = changedByKey.get(resolved);
|
|
20639
|
+
if (!changed) continue;
|
|
20640
|
+
const used = perFile.get(h.file) ?? 0;
|
|
20641
|
+
if (used >= MAX_IMPORTERS_PER_FILE) continue;
|
|
20642
|
+
perFile.set(h.file, used + 1);
|
|
20643
|
+
out.push({ file: h.file, line: h.line, text: h.text.trim().slice(0, SITE_TEXT_MAX), symbol: changed });
|
|
20644
|
+
}
|
|
20645
|
+
return out;
|
|
20646
|
+
}
|
|
20647
|
+
function runRg(args, cwd, timeoutMs) {
|
|
20648
|
+
let res = null;
|
|
20649
|
+
for (const inv of rgInvocations()) {
|
|
20650
|
+
res = (0, import_node_child_process10.spawnSync)(inv.cmd, args, {
|
|
20651
|
+
...inv.argv0 ? { argv0: inv.argv0 } : {},
|
|
20652
|
+
cwd,
|
|
20653
|
+
env: ripgrepEnv(),
|
|
20654
|
+
timeout: timeoutMs,
|
|
20655
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
20656
|
+
encoding: "utf8"
|
|
20657
|
+
});
|
|
20658
|
+
if (res.error?.code !== "ENOENT") break;
|
|
20659
|
+
}
|
|
20660
|
+
if (!res || res.error?.code === "ENOENT") {
|
|
20661
|
+
return { ok: false, reason: "no-tool" };
|
|
20662
|
+
}
|
|
20663
|
+
if (res.error) {
|
|
20664
|
+
const code = res.error.code;
|
|
20665
|
+
return { ok: false, reason: code === "ETIMEDOUT" ? "timeout" : "error" };
|
|
20666
|
+
}
|
|
20667
|
+
if (res.signal) return { ok: false, reason: "timeout" };
|
|
20668
|
+
if (res.status !== 0 && res.status !== 1) return { ok: false, reason: "error" };
|
|
20669
|
+
return { ok: true, lines: (res.stdout ?? "").split("\n").map((l) => l.replace(/^\.\//, "")).filter(Boolean) };
|
|
20670
|
+
}
|
|
20671
|
+
function findImporters(input) {
|
|
20672
|
+
const basenames = [
|
|
20673
|
+
...new Set(input.changedPaths.map((p) => moduleKey(p).split("/").pop() ?? "").filter((b) => b.length > 0))
|
|
20674
|
+
].slice(0, MAX_SYMBOLS);
|
|
20675
|
+
if (basenames.length === 0) return [];
|
|
20676
|
+
const res = runRg(
|
|
20677
|
+
[
|
|
20678
|
+
"--no-config",
|
|
20679
|
+
"-n",
|
|
20680
|
+
"-w",
|
|
20681
|
+
"-F",
|
|
20682
|
+
"--no-heading",
|
|
20683
|
+
"--color",
|
|
20684
|
+
"never",
|
|
20685
|
+
"-m",
|
|
20686
|
+
"8",
|
|
20687
|
+
"--max-columns",
|
|
20688
|
+
"300",
|
|
20689
|
+
"--max-columns-preview",
|
|
20690
|
+
...basenames.flatMap((b) => ["-e", b]),
|
|
20691
|
+
"-g",
|
|
20692
|
+
"!**/{dist,build,out,vendor,node_modules,.git,coverage,target,__pycache__}/**",
|
|
20693
|
+
"./"
|
|
20694
|
+
],
|
|
20695
|
+
input.cwd,
|
|
20696
|
+
input.timeoutMs
|
|
20697
|
+
);
|
|
20698
|
+
if (!res.ok) return [];
|
|
20699
|
+
return partitionImporters(res.lines, input.changedPaths, {
|
|
20700
|
+
sentPaths: input.sentPaths,
|
|
20701
|
+
isExcluded: input.isExcluded
|
|
20702
|
+
});
|
|
20703
|
+
}
|
|
20398
20704
|
function buildRepoContext(input) {
|
|
20399
20705
|
const started = Date.now();
|
|
20400
20706
|
let signalsByPath;
|
|
@@ -20429,7 +20735,18 @@ function buildRepoContext(input) {
|
|
|
20429
20735
|
const unsupportedExts = [...unsupported].sort().slice(0, 8);
|
|
20430
20736
|
const audit = unsupportedExts.length > 0 ? { unsupported_exts: unsupportedExts } : {};
|
|
20431
20737
|
const symbols = rankSymbols([...new Set(collected)]);
|
|
20738
|
+
const changedPaths = [.../* @__PURE__ */ new Set([...signalsByPath.keys(), ...input.deltaFiles.map((f) => f.path)])];
|
|
20739
|
+
const importers = findImporters({
|
|
20740
|
+
changedPaths,
|
|
20741
|
+
sentPaths: input.sentPaths,
|
|
20742
|
+
isExcluded: input.isExcluded,
|
|
20743
|
+
cwd: input.cwd ?? process.cwd(),
|
|
20744
|
+
timeoutMs: input.timeoutMs ?? RG_TIMEOUT_MS
|
|
20745
|
+
});
|
|
20432
20746
|
if (symbols.length === 0) {
|
|
20747
|
+
if (importers.length > 0) {
|
|
20748
|
+
return { state: "ok", symbols: [], ...audit, callers: [], tests: [], importers, elapsed_ms: Date.now() - started };
|
|
20749
|
+
}
|
|
20433
20750
|
const everySupportedFileFoundNothing = unsupportedExts.length > 0;
|
|
20434
20751
|
return {
|
|
20435
20752
|
state: "absent",
|
|
@@ -20468,34 +20785,19 @@ function buildRepoContext(input) {
|
|
|
20468
20785
|
"!**/{dist,build,out,vendor,node_modules,.git,coverage,target,__pycache__}/**",
|
|
20469
20786
|
"./"
|
|
20470
20787
|
];
|
|
20471
|
-
|
|
20472
|
-
|
|
20473
|
-
|
|
20474
|
-
...
|
|
20475
|
-
|
|
20476
|
-
|
|
20477
|
-
timeout: input.timeoutMs ?? RG_TIMEOUT_MS,
|
|
20478
|
-
maxBuffer: 4 * 1024 * 1024,
|
|
20479
|
-
encoding: "utf8"
|
|
20480
|
-
});
|
|
20481
|
-
if (res.error?.code !== "ENOENT") break;
|
|
20482
|
-
}
|
|
20483
|
-
if (!res || res.error?.code === "ENOENT") {
|
|
20484
|
-
return { state: "absent", reason: "no-tool", symbols, ...audit };
|
|
20485
|
-
}
|
|
20486
|
-
if (res.error) {
|
|
20487
|
-
const code = res.error.code;
|
|
20488
|
-
if (code === "ETIMEDOUT") return { state: "absent", reason: "timeout", symbols, ...audit };
|
|
20489
|
-
return { state: "absent", reason: "error", symbols, ...audit };
|
|
20788
|
+
const res = runRg(args, input.cwd ?? process.cwd(), input.timeoutMs ?? RG_TIMEOUT_MS);
|
|
20789
|
+
if (!res.ok) {
|
|
20790
|
+
if (importers.length > 0) {
|
|
20791
|
+
return { state: "ok", symbols, ...audit, callers: [], tests: [], importers, elapsed_ms: Date.now() - started };
|
|
20792
|
+
}
|
|
20793
|
+
return { state: "absent", reason: res.reason, symbols, ...audit };
|
|
20490
20794
|
}
|
|
20491
|
-
|
|
20492
|
-
if (res.status !== 0 && res.status !== 1) return { state: "absent", reason: "error", symbols, ...audit };
|
|
20493
|
-
const lines = (res.stdout ?? "").split("\n").map((l) => l.replace(/^\.\//, "")).filter(Boolean);
|
|
20795
|
+
const lines = res.lines;
|
|
20494
20796
|
const { callers, tests, dropped } = partitionSites(lines, symbols, {
|
|
20495
20797
|
sentPaths: input.sentPaths,
|
|
20496
20798
|
isExcluded: input.isExcluded
|
|
20497
20799
|
});
|
|
20498
|
-
if (callers.length === 0 && tests.length === 0) {
|
|
20800
|
+
if (callers.length === 0 && tests.length === 0 && importers.length === 0) {
|
|
20499
20801
|
return {
|
|
20500
20802
|
state: "absent",
|
|
20501
20803
|
reason: "no-sites",
|
|
@@ -20512,6 +20814,7 @@ function buildRepoContext(input) {
|
|
|
20512
20814
|
...audit,
|
|
20513
20815
|
callers,
|
|
20514
20816
|
tests,
|
|
20817
|
+
...importers.length > 0 ? { importers } : {},
|
|
20515
20818
|
elapsed_ms: Date.now() - started
|
|
20516
20819
|
};
|
|
20517
20820
|
}
|
|
@@ -20579,12 +20882,17 @@ function upgradeToExcerpts(rc, opts) {
|
|
|
20579
20882
|
}
|
|
20580
20883
|
function describeRepoContext(rc) {
|
|
20581
20884
|
if (rc.state !== "ok") {
|
|
20582
|
-
const
|
|
20583
|
-
|
|
20885
|
+
const bits = [
|
|
20886
|
+
rc.symbols?.length ? `searched: ${rc.symbols.join(", ")}` : "",
|
|
20887
|
+
rc.dropped_symbols?.length ? `dropped too-common: ${rc.dropped_symbols.join(", ")}` : "",
|
|
20888
|
+
rc.unsupported_exts?.length ? `no rules for: ${rc.unsupported_exts.join(", ")}` : ""
|
|
20889
|
+
].filter(Boolean);
|
|
20890
|
+
return `absent (${rc.reason ?? "unknown"})${bits.length > 0 ? ` \xB7 ${bits.join(" \xB7 ")}` : ""}`;
|
|
20584
20891
|
}
|
|
20585
20892
|
const parts = [
|
|
20586
20893
|
`${rc.symbols?.length ?? 0} symbol(s) \u2192 ${rc.callers?.length ?? 0} caller(s) \xB7 ${rc.tests?.length ?? 0} test(s)`
|
|
20587
20894
|
];
|
|
20895
|
+
if (rc.importers?.length) parts.push(`${rc.importers.length} importer(s)`);
|
|
20588
20896
|
if (rc.excerpts?.length) parts.push(`${rc.excerpts.length} excerpt(s)`);
|
|
20589
20897
|
if (rc.dropped_symbols?.length) parts.push(`dropped too-common: ${rc.dropped_symbols.join(", ")}`);
|
|
20590
20898
|
if (rc.unsupported_exts?.length) parts.push(`no rules for: ${rc.unsupported_exts.join(", ")}`);
|
|
@@ -20712,10 +21020,10 @@ function installRunEvidence(run2) {
|
|
|
20712
21020
|
}
|
|
20713
21021
|
|
|
20714
21022
|
// src/lib/git-frame.ts
|
|
20715
|
-
var
|
|
20716
|
-
var
|
|
20717
|
-
var
|
|
20718
|
-
var
|
|
21023
|
+
var import_node_fs35 = require("node:fs");
|
|
21024
|
+
var import_node_os6 = require("node:os");
|
|
21025
|
+
var import_node_path27 = require("node:path");
|
|
21026
|
+
var import_node_path28 = require("node:path");
|
|
20719
21027
|
|
|
20720
21028
|
// src/lib/hardened-git.ts
|
|
20721
21029
|
var import_node_child_process11 = require("node:child_process");
|
|
@@ -20870,15 +21178,15 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
20870
21178
|
if (!m) continue;
|
|
20871
21179
|
named = true;
|
|
20872
21180
|
if (m[1] === void 0) {
|
|
20873
|
-
dir = (0,
|
|
21181
|
+
dir = (0, import_node_os6.homedir)();
|
|
20874
21182
|
continue;
|
|
20875
21183
|
}
|
|
20876
21184
|
const raw = unquote(m[1]);
|
|
20877
21185
|
if (SHELL_DYNAMIC.test(raw) || raw === "-") {
|
|
20878
21186
|
return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
|
|
20879
21187
|
}
|
|
20880
|
-
const expanded = raw === "~" ? (0,
|
|
20881
|
-
dir = (0,
|
|
21188
|
+
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path28.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
|
|
21189
|
+
dir = (0, import_node_path27.isAbsolute)(expanded) ? expanded : (0, import_node_path27.resolve)(dir, expanded);
|
|
20882
21190
|
}
|
|
20883
21191
|
const seg = segments[segmentIndex];
|
|
20884
21192
|
const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
|
|
@@ -20896,8 +21204,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
20896
21204
|
if (SHELL_DYNAMIC.test(raw)) {
|
|
20897
21205
|
return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
|
|
20898
21206
|
}
|
|
20899
|
-
const expanded = raw === "~" ? (0,
|
|
20900
|
-
dir = (0,
|
|
21207
|
+
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path28.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
|
|
21208
|
+
dir = (0, import_node_path27.isAbsolute)(expanded) ? expanded : (0, import_node_path27.resolve)(dir, expanded);
|
|
20901
21209
|
}
|
|
20902
21210
|
}
|
|
20903
21211
|
return { dir, named, unresolvable: null };
|
|
@@ -20957,14 +21265,14 @@ function gitAt(dir, args) {
|
|
|
20957
21265
|
}
|
|
20958
21266
|
function realpathOr2(p) {
|
|
20959
21267
|
try {
|
|
20960
|
-
return
|
|
21268
|
+
return import_node_fs35.realpathSync.native(p);
|
|
20961
21269
|
} catch {
|
|
20962
|
-
return (0,
|
|
21270
|
+
return (0, import_node_path27.resolve)(p);
|
|
20963
21271
|
}
|
|
20964
21272
|
}
|
|
20965
21273
|
function resolveFrame(input) {
|
|
20966
21274
|
const found = findMomentSegment(input.command, input.on);
|
|
20967
|
-
const hookDirUsable = !!input.hookCwd && (0,
|
|
21275
|
+
const hookDirUsable = !!input.hookCwd && (0, import_node_fs35.existsSync)(input.hookCwd);
|
|
20968
21276
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
20969
21277
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
20970
21278
|
const refuse = (refusal) => ({
|
|
@@ -20987,7 +21295,7 @@ function resolveFrame(input) {
|
|
|
20987
21295
|
if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
|
|
20988
21296
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
20989
21297
|
if (targetDir !== baseDir) {
|
|
20990
|
-
if (!(0,
|
|
21298
|
+
if (!(0, import_node_fs35.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
|
|
20991
21299
|
dir = targetDir;
|
|
20992
21300
|
}
|
|
20993
21301
|
}
|
|
@@ -20998,7 +21306,7 @@ function resolveFrame(input) {
|
|
|
20998
21306
|
const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
|
|
20999
21307
|
const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
|
|
21000
21308
|
const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
|
|
21001
|
-
const commonDir = commonRaw ? realpathOr2((0,
|
|
21309
|
+
const commonDir = commonRaw ? realpathOr2((0, import_node_path27.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path27.resolve)(dir, commonRaw)) : null;
|
|
21002
21310
|
const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
21003
21311
|
return {
|
|
21004
21312
|
moment: found?.moment ?? null,
|
|
@@ -21173,8 +21481,8 @@ function stagedRange(frame, command) {
|
|
|
21173
21481
|
if (plan.kind === "unpredictable") {
|
|
21174
21482
|
return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
|
|
21175
21483
|
}
|
|
21176
|
-
const mergeHead = frame.gitDir ? (0,
|
|
21177
|
-
if (mergeHead && (0,
|
|
21484
|
+
const mergeHead = frame.gitDir ? (0, import_node_path28.join)(frame.gitDir, "MERGE_HEAD") : null;
|
|
21485
|
+
if (mergeHead && (0, import_node_fs35.existsSync)(mergeHead)) {
|
|
21178
21486
|
const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
|
|
21179
21487
|
const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
|
|
21180
21488
|
const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
|
|
@@ -21308,7 +21616,7 @@ function truthy(v) {
|
|
|
21308
21616
|
}
|
|
21309
21617
|
|
|
21310
21618
|
// src/lib/transcript.ts
|
|
21311
|
-
var
|
|
21619
|
+
var import_node_fs36 = require("node:fs");
|
|
21312
21620
|
var MAX_READ_BYTES = 256 * 1024;
|
|
21313
21621
|
var SMALL_FILE_BYTES = 64 * 1024;
|
|
21314
21622
|
var MAX_FILES_LIST = 20;
|
|
@@ -21335,7 +21643,7 @@ async function extractActionSummary(transcriptPath) {
|
|
|
21335
21643
|
function readTurnLines(transcriptPath) {
|
|
21336
21644
|
let size;
|
|
21337
21645
|
try {
|
|
21338
|
-
size = (0,
|
|
21646
|
+
size = (0, import_node_fs36.statSync)(transcriptPath).size;
|
|
21339
21647
|
} catch {
|
|
21340
21648
|
return null;
|
|
21341
21649
|
}
|
|
@@ -21343,7 +21651,7 @@ function readTurnLines(transcriptPath) {
|
|
|
21343
21651
|
let raw;
|
|
21344
21652
|
let windowed = false;
|
|
21345
21653
|
if (size <= SMALL_FILE_BYTES) {
|
|
21346
|
-
raw = (0,
|
|
21654
|
+
raw = (0, import_node_fs36.readFileSync)(transcriptPath, "utf-8");
|
|
21347
21655
|
} else {
|
|
21348
21656
|
windowed = true;
|
|
21349
21657
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
@@ -21851,7 +22159,7 @@ function channelSilence(input) {
|
|
|
21851
22159
|
// src/lib/cli-version.ts
|
|
21852
22160
|
function cliVersion() {
|
|
21853
22161
|
try {
|
|
21854
|
-
return true ? "0.33.
|
|
22162
|
+
return true ? "0.33.1-experimental.1378de3" : "dev";
|
|
21855
22163
|
} catch {
|
|
21856
22164
|
return "dev";
|
|
21857
22165
|
}
|
|
@@ -21892,7 +22200,7 @@ async function sendSkipBeacon(ctx, reason) {
|
|
|
21892
22200
|
|
|
21893
22201
|
// src/lib/static-analysis.ts
|
|
21894
22202
|
var import_node_child_process12 = require("node:child_process");
|
|
21895
|
-
var
|
|
22203
|
+
var import_node_fs37 = require("node:fs");
|
|
21896
22204
|
var SEVERITY_ORDER = {
|
|
21897
22205
|
Error: 0,
|
|
21898
22206
|
Critical: 0,
|
|
@@ -21903,12 +22211,10 @@ var SEVERITY_ORDER = {
|
|
|
21903
22211
|
Low: 3
|
|
21904
22212
|
};
|
|
21905
22213
|
function isCodacyAvailable() {
|
|
21906
|
-
|
|
21907
|
-
|
|
21908
|
-
|
|
21909
|
-
|
|
21910
|
-
return false;
|
|
21911
|
-
}
|
|
22214
|
+
return codacyAnalysisPath() !== null;
|
|
22215
|
+
}
|
|
22216
|
+
function codacyAnalysisPath() {
|
|
22217
|
+
return whichSync("codacy-analysis");
|
|
21912
22218
|
}
|
|
21913
22219
|
function buildAnalyzerArgv(files) {
|
|
21914
22220
|
return [
|
|
@@ -21935,18 +22241,29 @@ function withFailure(kind, detail) {
|
|
|
21935
22241
|
summary: { ...EMPTY_RESULT.summary, failure: { kind, detail: detail.slice(0, 300) } }
|
|
21936
22242
|
};
|
|
21937
22243
|
}
|
|
22244
|
+
function runCodacyAnalysisIfAvailable(files) {
|
|
22245
|
+
if (files.length === 0) return EMPTY_RESULT;
|
|
22246
|
+
if (!isCodacyAvailable()) {
|
|
22247
|
+
return withFailure(
|
|
22248
|
+
"analyzer_unavailable",
|
|
22249
|
+
"@codacy/analysis-cli was not found on PATH \u2014 no static analysis ran"
|
|
22250
|
+
);
|
|
22251
|
+
}
|
|
22252
|
+
return runCodacyAnalysis(files);
|
|
22253
|
+
}
|
|
21938
22254
|
function runCodacyAnalysis(files) {
|
|
21939
22255
|
const empty = EMPTY_RESULT;
|
|
21940
22256
|
if (files.length === 0) return empty;
|
|
21941
22257
|
const existingFiles = files.filter((f) => {
|
|
21942
22258
|
try {
|
|
21943
|
-
return (0,
|
|
22259
|
+
return (0, import_node_fs37.existsSync)(f);
|
|
21944
22260
|
} catch {
|
|
21945
22261
|
return false;
|
|
21946
22262
|
}
|
|
21947
22263
|
});
|
|
21948
22264
|
if (existingFiles.length === 0) return empty;
|
|
21949
|
-
const
|
|
22265
|
+
const analyzer = codacyAnalysisPath() ?? "codacy-analysis";
|
|
22266
|
+
const proc = (0, import_node_child_process12.spawnSync)(analyzer, buildAnalyzerArgv(existingFiles), {
|
|
21950
22267
|
encoding: "utf-8",
|
|
21951
22268
|
maxBuffer: 10 * 1024 * 1024
|
|
21952
22269
|
});
|
|
@@ -22114,11 +22431,10 @@ var EMPTY_STATIC = {
|
|
|
22114
22431
|
summary: { total_findings: 0, by_severity: {}, tools_run: [] }
|
|
22115
22432
|
};
|
|
22116
22433
|
function runLocalStatic(analyzable, securityFiles, baseline, skipStatic) {
|
|
22117
|
-
if (skipStatic
|
|
22434
|
+
if (skipStatic) return EMPTY_STATIC;
|
|
22118
22435
|
let scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
22119
22436
|
if (baseline) scannable = scannable.filter((f) => changedSinceBaseline(f, baseline));
|
|
22120
|
-
|
|
22121
|
-
return runCodacyAnalysis(scannable);
|
|
22437
|
+
return runCodacyAnalysisIfAvailable(scannable);
|
|
22122
22438
|
}
|
|
22123
22439
|
function localOnlyAndExit(staticResults) {
|
|
22124
22440
|
printJsonCompact({
|
|
@@ -22209,8 +22525,8 @@ async function scope(run2) {
|
|
|
22209
22525
|
}
|
|
22210
22526
|
|
|
22211
22527
|
// src/lib/specs.ts
|
|
22212
|
-
var
|
|
22213
|
-
var
|
|
22528
|
+
var import_node_fs38 = require("node:fs");
|
|
22529
|
+
var import_node_path29 = require("node:path");
|
|
22214
22530
|
var SPEC_CANDIDATES = [
|
|
22215
22531
|
"CLAUDE.md",
|
|
22216
22532
|
"AGENTS.md",
|
|
@@ -22229,6 +22545,16 @@ var SPEC_CANDIDATES = [
|
|
|
22229
22545
|
var DOC_EXT = /\.(md|mdx|ya?ml|txt|rst|adoc)$/i;
|
|
22230
22546
|
var UNCONSULTED_FILE_BYTES = 10240;
|
|
22231
22547
|
var UNCONSULTED_TOTAL_BYTES = 30720;
|
|
22548
|
+
function readSpecFiles(specsOpt, root) {
|
|
22549
|
+
const out = [];
|
|
22550
|
+
for (const raw of specsOpt.split(",").map((f) => f.trim()).filter(Boolean)) {
|
|
22551
|
+
const candidate = (0, import_node_path29.isAbsolute)(raw) ? (0, import_node_path29.relative)(root, raw) : raw;
|
|
22552
|
+
const content = readFileInside(root, candidate, MAX_EXPLICIT_SPEC_FILE_BYTES);
|
|
22553
|
+
if (content === null) continue;
|
|
22554
|
+
out.push({ path: raw, content });
|
|
22555
|
+
}
|
|
22556
|
+
return out;
|
|
22557
|
+
}
|
|
22232
22558
|
function discoverSpecs(consulted = []) {
|
|
22233
22559
|
const result = [];
|
|
22234
22560
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -22241,7 +22567,7 @@ function discoverSpecs(consulted = []) {
|
|
|
22241
22567
|
const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
|
|
22242
22568
|
if (totalBytes >= totalCap) return false;
|
|
22243
22569
|
if (seen.has(specPath)) return true;
|
|
22244
|
-
if (!(0,
|
|
22570
|
+
if (!(0, import_node_fs38.existsSync)(specPath)) return true;
|
|
22245
22571
|
seen.add(specPath);
|
|
22246
22572
|
const remaining = totalCap - totalBytes;
|
|
22247
22573
|
const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
|
|
@@ -22264,7 +22590,7 @@ function discoverSpecs(consulted = []) {
|
|
|
22264
22590
|
if (!addSpec(candidate)) break;
|
|
22265
22591
|
}
|
|
22266
22592
|
for (const dir of ["spec", "docs"]) {
|
|
22267
|
-
if (!(0,
|
|
22593
|
+
if (!(0, import_node_fs38.existsSync)(dir)) continue;
|
|
22268
22594
|
try {
|
|
22269
22595
|
const mdFiles = findMdFiles(dir, 2).sort();
|
|
22270
22596
|
for (const mdFile of mdFiles) {
|
|
@@ -22279,9 +22605,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
22279
22605
|
if (depth >= maxDepth) return [];
|
|
22280
22606
|
const result = [];
|
|
22281
22607
|
try {
|
|
22282
|
-
const entries = (0,
|
|
22608
|
+
const entries = (0, import_node_fs38.readdirSync)(dir, { withFileTypes: true });
|
|
22283
22609
|
for (const entry of entries) {
|
|
22284
|
-
const fullPath = (0,
|
|
22610
|
+
const fullPath = (0, import_node_path29.join)(dir, entry.name);
|
|
22285
22611
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
22286
22612
|
result.push(fullPath);
|
|
22287
22613
|
} else if (entry.isDirectory() && depth < maxDepth - 1) {
|
|
@@ -22294,25 +22620,25 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
22294
22620
|
}
|
|
22295
22621
|
function discoverPlans() {
|
|
22296
22622
|
const home = process.env.HOME ?? "";
|
|
22297
|
-
const homePlansDir = (0,
|
|
22623
|
+
const homePlansDir = (0, import_node_path29.join)(home, ".claude", "plans");
|
|
22298
22624
|
const sources = [];
|
|
22299
22625
|
if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
|
|
22300
|
-
sources.push({ root: process.cwd(), prefix: (0,
|
|
22626
|
+
sources.push({ root: process.cwd(), prefix: (0, import_node_path29.join)(".claude", "plans") });
|
|
22301
22627
|
}
|
|
22302
|
-
if (home && (0,
|
|
22628
|
+
if (home && (0, import_node_fs38.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
|
|
22303
22629
|
const candidates2 = [];
|
|
22304
22630
|
const seen = /* @__PURE__ */ new Set();
|
|
22305
22631
|
for (const source of sources) {
|
|
22306
22632
|
let names2;
|
|
22307
22633
|
try {
|
|
22308
|
-
names2 = (0,
|
|
22634
|
+
names2 = (0, import_node_fs38.readdirSync)(source.prefix ? (0, import_node_path29.join)(source.root, source.prefix) : source.root);
|
|
22309
22635
|
} catch {
|
|
22310
22636
|
continue;
|
|
22311
22637
|
}
|
|
22312
22638
|
for (const f of names2) {
|
|
22313
22639
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
22314
22640
|
seen.add(f);
|
|
22315
|
-
const relPath = source.prefix ? (0,
|
|
22641
|
+
const relPath = source.prefix ? (0, import_node_path29.join)(source.prefix, f) : f;
|
|
22316
22642
|
const stat3 = statRegularInRoot(source.root, relPath);
|
|
22317
22643
|
if (!stat3.ok) continue;
|
|
22318
22644
|
candidates2.push({ name: f, root: source.root, relPath, mtime: stat3.mtimeMs, size: stat3.size });
|
|
@@ -22330,9 +22656,9 @@ function discoverPlans() {
|
|
|
22330
22656
|
function isRealDirectoryChain(root, parts) {
|
|
22331
22657
|
let current = root;
|
|
22332
22658
|
for (const part of parts) {
|
|
22333
|
-
current = (0,
|
|
22659
|
+
current = (0, import_node_path29.join)(current, part);
|
|
22334
22660
|
try {
|
|
22335
|
-
if (!(0,
|
|
22661
|
+
if (!(0, import_node_fs38.lstatSync)(current).isDirectory()) return false;
|
|
22336
22662
|
} catch {
|
|
22337
22663
|
return false;
|
|
22338
22664
|
}
|
|
@@ -22347,7 +22673,7 @@ function discoverGuardDocs(rangeFiles2) {
|
|
|
22347
22673
|
if (result.length >= MAX_SPEC_FILES) break;
|
|
22348
22674
|
if (!GUARD_DOC_EXT.test(path)) continue;
|
|
22349
22675
|
if (path.startsWith("/") || path.includes("..")) continue;
|
|
22350
|
-
if (!(0,
|
|
22676
|
+
if (!(0, import_node_fs38.existsSync)(path)) continue;
|
|
22351
22677
|
const opened = openRegularInRoot(process.cwd(), path);
|
|
22352
22678
|
if (!opened.ok) continue;
|
|
22353
22679
|
if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
|
|
@@ -22533,8 +22859,8 @@ async function mode(run2) {
|
|
|
22533
22859
|
}
|
|
22534
22860
|
|
|
22535
22861
|
// src/lib/fold.ts
|
|
22536
|
-
var
|
|
22537
|
-
var
|
|
22862
|
+
var import_node_fs39 = require("node:fs");
|
|
22863
|
+
var import_node_path30 = require("node:path");
|
|
22538
22864
|
var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
|
|
22539
22865
|
"user",
|
|
22540
22866
|
"assistant",
|
|
@@ -22671,7 +22997,7 @@ function candidateRoots(repoRoot2) {
|
|
|
22671
22997
|
const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
22672
22998
|
const out = [norm];
|
|
22673
22999
|
try {
|
|
22674
|
-
const real =
|
|
23000
|
+
const real = import_node_fs39.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
22675
23001
|
if (real !== norm) out.push(real);
|
|
22676
23002
|
} catch {
|
|
22677
23003
|
}
|
|
@@ -22759,31 +23085,31 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22759
23085
|
}
|
|
22760
23086
|
};
|
|
22761
23087
|
try {
|
|
22762
|
-
if (!(0,
|
|
22763
|
-
ingest((0,
|
|
23088
|
+
if (!(0, import_node_fs39.existsSync)(transcriptPath)) return result;
|
|
23089
|
+
ingest((0, import_node_fs39.readFileSync)(transcriptPath, "utf8"), "agent");
|
|
22764
23090
|
result.coverage.complete = true;
|
|
22765
23091
|
} catch {
|
|
22766
23092
|
return result;
|
|
22767
23093
|
}
|
|
22768
23094
|
try {
|
|
22769
|
-
const sidecarDir = (0,
|
|
22770
|
-
(0,
|
|
22771
|
-
(0,
|
|
23095
|
+
const sidecarDir = (0, import_node_path30.join)(
|
|
23096
|
+
(0, import_node_path30.dirname)(transcriptPath),
|
|
23097
|
+
(0, import_node_path30.basename)(transcriptPath).replace(/\.jsonl$/, ""),
|
|
22772
23098
|
"subagents"
|
|
22773
23099
|
);
|
|
22774
|
-
if ((0,
|
|
23100
|
+
if ((0, import_node_fs39.existsSync)(sidecarDir)) {
|
|
22775
23101
|
const maxFiles = opts.maxSidecars ?? 200;
|
|
22776
23102
|
const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
|
|
22777
23103
|
const found = [];
|
|
22778
23104
|
const walk2 = (d, depth) => {
|
|
22779
23105
|
if (depth > 4) return;
|
|
22780
|
-
for (const e of (0,
|
|
22781
|
-
const p = (0,
|
|
23106
|
+
for (const e of (0, import_node_fs39.readdirSync)(d, { withFileTypes: true })) {
|
|
23107
|
+
const p = (0, import_node_path30.join)(d, e.name);
|
|
22782
23108
|
if (e.isDirectory()) {
|
|
22783
23109
|
walk2(p, depth + 1);
|
|
22784
23110
|
} else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
|
|
22785
23111
|
try {
|
|
22786
|
-
const st = (0,
|
|
23112
|
+
const st = (0, import_node_fs39.statSync)(p);
|
|
22787
23113
|
found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
|
|
22788
23114
|
} catch {
|
|
22789
23115
|
result.coverage.malformed++;
|
|
@@ -22800,7 +23126,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22800
23126
|
continue;
|
|
22801
23127
|
}
|
|
22802
23128
|
try {
|
|
22803
|
-
ingest((0,
|
|
23129
|
+
ingest((0, import_node_fs39.readFileSync)(f.path, "utf8"), "subagent");
|
|
22804
23130
|
bytes += f.size;
|
|
22805
23131
|
result.coverage.subagentFiles++;
|
|
22806
23132
|
} catch {
|
|
@@ -22835,7 +23161,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22835
23161
|
}
|
|
22836
23162
|
function classifyUnobserved(path) {
|
|
22837
23163
|
try {
|
|
22838
|
-
const st = (0,
|
|
23164
|
+
const st = (0, import_node_fs39.statSync)(path);
|
|
22839
23165
|
if (!st.isFile()) return "unreadable";
|
|
22840
23166
|
} catch {
|
|
22841
23167
|
return "unreadable";
|
|
@@ -23102,14 +23428,12 @@ async function evidence(run2) {
|
|
|
23102
23428
|
authorshipWasObservable
|
|
23103
23429
|
});
|
|
23104
23430
|
const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
|
|
23105
|
-
if (!opts.skipStatic
|
|
23431
|
+
if (!opts.skipStatic) {
|
|
23106
23432
|
let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
23107
23433
|
if (baseline) {
|
|
23108
23434
|
allScannable = allScannable.filter((f) => changedSinceBaseline(f, baseline));
|
|
23109
23435
|
}
|
|
23110
|
-
|
|
23111
|
-
staticResults = runCodacyAnalysis(allScannable);
|
|
23112
|
-
}
|
|
23436
|
+
staticResults = runCodacyAnalysisIfAvailable(allScannable);
|
|
23113
23437
|
}
|
|
23114
23438
|
const deltaSet = baseline ? recentForReview.filter((f) => changedSinceBaseline(f, baseline)) : recentForReview;
|
|
23115
23439
|
codeDelta = collectCodeDelta(deltaSet, {
|
|
@@ -23152,20 +23476,20 @@ async function evidence(run2) {
|
|
|
23152
23476
|
}
|
|
23153
23477
|
|
|
23154
23478
|
// src/lib/cache-cleanup.ts
|
|
23155
|
-
var
|
|
23156
|
-
var
|
|
23479
|
+
var import_node_fs40 = require("node:fs");
|
|
23480
|
+
var import_node_path31 = require("node:path");
|
|
23157
23481
|
var CACHE_TTL_DAYS = 7;
|
|
23158
23482
|
function pruneStaleCache() {
|
|
23159
23483
|
try {
|
|
23160
23484
|
const dir = projectPath(CACHE_DIR);
|
|
23161
23485
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
23162
|
-
for (const entry of (0,
|
|
23486
|
+
for (const entry of (0, import_node_fs40.readdirSync)(dir)) {
|
|
23163
23487
|
if (!entry.startsWith("pending-")) continue;
|
|
23164
|
-
const path = (0,
|
|
23488
|
+
const path = (0, import_node_path31.join)(dir, entry);
|
|
23165
23489
|
try {
|
|
23166
|
-
const stat3 = (0,
|
|
23490
|
+
const stat3 = (0, import_node_fs40.statSync)(path);
|
|
23167
23491
|
if (stat3.mtimeMs < cutoff) {
|
|
23168
|
-
(0,
|
|
23492
|
+
(0, import_node_fs40.unlinkSync)(path);
|
|
23169
23493
|
logEvent("cache_entry_pruned", {
|
|
23170
23494
|
path: entry,
|
|
23171
23495
|
age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
|
|
@@ -23179,8 +23503,8 @@ function pruneStaleCache() {
|
|
|
23179
23503
|
}
|
|
23180
23504
|
|
|
23181
23505
|
// src/lib/context-files.ts
|
|
23182
|
-
var
|
|
23183
|
-
var
|
|
23506
|
+
var import_node_fs41 = require("node:fs");
|
|
23507
|
+
var import_node_os7 = require("node:os");
|
|
23184
23508
|
var MAX_CONTEXT_FILES = 10;
|
|
23185
23509
|
var MAX_CONTEXT_FILE_BYTES = 10240;
|
|
23186
23510
|
var MAX_CONTEXT_TOTAL_BYTES = 24576;
|
|
@@ -23188,7 +23512,7 @@ function readSetContextPaths(summary, deltaFiles) {
|
|
|
23188
23512
|
const reads = summary?.files_read ?? [];
|
|
23189
23513
|
if (reads.length === 0) return [];
|
|
23190
23514
|
const root = process.cwd().replace(/\/+$/, "");
|
|
23191
|
-
const home = (0,
|
|
23515
|
+
const home = (0, import_node_os7.homedir)();
|
|
23192
23516
|
const toRepoRelative2 = (p) => {
|
|
23193
23517
|
if (!p) return null;
|
|
23194
23518
|
let abs;
|
|
@@ -23237,7 +23561,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
|
|
|
23237
23561
|
continue;
|
|
23238
23562
|
}
|
|
23239
23563
|
try {
|
|
23240
|
-
const content = (0,
|
|
23564
|
+
const content = (0, import_node_fs41.readFileSync)(safePath, "utf8");
|
|
23241
23565
|
const bytes = Buffer.byteLength(content);
|
|
23242
23566
|
if (bytes > MAX_CONTEXT_FILE_BYTES) {
|
|
23243
23567
|
logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
|
|
@@ -23322,14 +23646,15 @@ async function repoContext(run2) {
|
|
|
23322
23646
|
dropped: run2.repoContext.dropped_symbols?.length ?? 0,
|
|
23323
23647
|
callers: run2.repoContext.callers?.length ?? 0,
|
|
23324
23648
|
tests: run2.repoContext.tests?.length ?? 0,
|
|
23649
|
+
importers: run2.repoContext.importers?.length ?? 0,
|
|
23325
23650
|
elapsed_ms: run2.repoContext.elapsed_ms ?? null
|
|
23326
23651
|
});
|
|
23327
23652
|
}
|
|
23328
23653
|
|
|
23329
23654
|
// src/lib/seed-runner.ts
|
|
23330
23655
|
var import_promises15 = require("node:fs/promises");
|
|
23331
|
-
var
|
|
23332
|
-
var
|
|
23656
|
+
var import_node_fs42 = require("node:fs");
|
|
23657
|
+
var import_node_path32 = require("node:path");
|
|
23333
23658
|
var import_yaml4 = __toESM(require_dist());
|
|
23334
23659
|
|
|
23335
23660
|
// src/lib/seed.ts
|
|
@@ -23568,7 +23893,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
|
|
|
23568
23893
|
return fm;
|
|
23569
23894
|
}
|
|
23570
23895
|
async function runSeed(opts) {
|
|
23571
|
-
if (!(0,
|
|
23896
|
+
if (!(0, import_node_fs42.existsSync)(STANDARD_FILE)) {
|
|
23572
23897
|
return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
|
|
23573
23898
|
}
|
|
23574
23899
|
let standardDoc;
|
|
@@ -23580,7 +23905,7 @@ async function runSeed(opts) {
|
|
|
23580
23905
|
}
|
|
23581
23906
|
const knowledgeSpec = standardDoc.knowledge_spec ?? {};
|
|
23582
23907
|
let readmeContent;
|
|
23583
|
-
if ((0,
|
|
23908
|
+
if ((0, import_node_fs42.existsSync)("README.md")) {
|
|
23584
23909
|
try {
|
|
23585
23910
|
readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
|
|
23586
23911
|
} catch {
|
|
@@ -23588,7 +23913,7 @@ async function runSeed(opts) {
|
|
|
23588
23913
|
}
|
|
23589
23914
|
let claudeMdContent;
|
|
23590
23915
|
for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
|
|
23591
|
-
if ((0,
|
|
23916
|
+
if ((0, import_node_fs42.existsSync)(p)) {
|
|
23592
23917
|
try {
|
|
23593
23918
|
claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
|
|
23594
23919
|
break;
|
|
@@ -23611,8 +23936,8 @@ async function runSeed(opts) {
|
|
|
23611
23936
|
if (candidates2.length === 0) {
|
|
23612
23937
|
return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
|
|
23613
23938
|
}
|
|
23614
|
-
const overviewPath = (0,
|
|
23615
|
-
if ((0,
|
|
23939
|
+
const overviewPath = (0, import_node_path32.join)(MEMORY_DIR, "domain", "project-overview.md");
|
|
23940
|
+
if ((0, import_node_fs42.existsSync)(overviewPath) && !opts.force) {
|
|
23616
23941
|
return { created: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
|
|
23617
23942
|
}
|
|
23618
23943
|
if (opts.dryRun) {
|
|
@@ -23654,7 +23979,7 @@ async function runSeed(opts) {
|
|
|
23654
23979
|
continue;
|
|
23655
23980
|
}
|
|
23656
23981
|
try {
|
|
23657
|
-
await (0, import_promises15.mkdir)((0,
|
|
23982
|
+
await (0, import_promises15.mkdir)((0, import_node_path32.dirname)(targetPath), { recursive: true });
|
|
23658
23983
|
await (0, import_promises15.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
|
|
23659
23984
|
created++;
|
|
23660
23985
|
opts.onCreated?.(nodeId, filePathRel, c);
|
|
@@ -23667,8 +23992,8 @@ async function runSeed(opts) {
|
|
|
23667
23992
|
}
|
|
23668
23993
|
|
|
23669
23994
|
// src/commands/analyze/phases/08-memory-manifest.ts
|
|
23670
|
-
var
|
|
23671
|
-
var
|
|
23995
|
+
var import_node_fs43 = require("node:fs");
|
|
23996
|
+
var import_node_path33 = require("node:path");
|
|
23672
23997
|
async function memoryManifest(run2) {
|
|
23673
23998
|
const { globals } = run2;
|
|
23674
23999
|
const { serviceUrl, token } = run2;
|
|
@@ -23678,9 +24003,9 @@ async function memoryManifest(run2) {
|
|
|
23678
24003
|
let autoSeedNotice = null;
|
|
23679
24004
|
try {
|
|
23680
24005
|
await ensureMemoryDir();
|
|
23681
|
-
const seedMarker = (0,
|
|
23682
|
-
const hasStandard = (0,
|
|
23683
|
-
const alreadyTried = (0,
|
|
24006
|
+
const seedMarker = (0, import_node_path33.join)(VERITY_DIR, ".seeded");
|
|
24007
|
+
const hasStandard = (0, import_node_fs43.existsSync)(STANDARD_FILE);
|
|
24008
|
+
const alreadyTried = (0, import_node_fs43.existsSync)(seedMarker);
|
|
23684
24009
|
if (hasStandard && !alreadyTried) {
|
|
23685
24010
|
const preManifest = await buildManifest();
|
|
23686
24011
|
if (preManifest.nodes.length === 0) {
|
|
@@ -23693,7 +24018,7 @@ async function memoryManifest(run2) {
|
|
|
23693
24018
|
dryRun: false
|
|
23694
24019
|
});
|
|
23695
24020
|
if (seedResult.created > 0) {
|
|
23696
|
-
(0,
|
|
24021
|
+
(0, import_node_fs43.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
|
|
23697
24022
|
`);
|
|
23698
24023
|
autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
|
|
23699
24024
|
logEvent("auto_seed_ran", {
|
|
@@ -23701,7 +24026,7 @@ async function memoryManifest(run2) {
|
|
|
23701
24026
|
failed: seedResult.failed
|
|
23702
24027
|
});
|
|
23703
24028
|
} else if (seedResult.skipped === "already_seeded") {
|
|
23704
|
-
(0,
|
|
24029
|
+
(0, import_node_fs43.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
|
|
23705
24030
|
`);
|
|
23706
24031
|
} else {
|
|
23707
24032
|
logEvent("auto_seed_noop", {
|
|
@@ -23796,7 +24121,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
|
|
|
23796
24121
|
}
|
|
23797
24122
|
|
|
23798
24123
|
// src/commands/analyze/phases/10-working-memory.ts
|
|
23799
|
-
var
|
|
24124
|
+
var import_node_path34 = require("node:path");
|
|
23800
24125
|
async function workingMemory(run2) {
|
|
23801
24126
|
const { opts } = run2;
|
|
23802
24127
|
const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run2;
|
|
@@ -23808,7 +24133,7 @@ async function workingMemory(run2) {
|
|
|
23808
24133
|
const priorState = foldForMarks(memorySession.d);
|
|
23809
24134
|
incrementReport = computeIncrement(
|
|
23810
24135
|
allForReview,
|
|
23811
|
-
(p) => fileHash((0,
|
|
24136
|
+
(p) => fileHash((0, import_node_path34.join)(repoRoot(), p)),
|
|
23812
24137
|
priorState.authored_all.map((a) => ({
|
|
23813
24138
|
path: a.path,
|
|
23814
24139
|
hash_at_last_verdict: a.hash_at_last_verdict
|
|
@@ -23890,7 +24215,7 @@ async function workingMemory(run2) {
|
|
|
23890
24215
|
}
|
|
23891
24216
|
|
|
23892
24217
|
// src/lib/note-budget.ts
|
|
23893
|
-
var
|
|
24218
|
+
var import_node_fs44 = require("node:fs");
|
|
23894
24219
|
var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
|
|
23895
24220
|
var EPISODE_STALE_SECONDS = 30 * 60;
|
|
23896
24221
|
var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
|
|
@@ -23912,9 +24237,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
|
|
|
23912
24237
|
}
|
|
23913
24238
|
function readAdvisoryEpisode(sessionId) {
|
|
23914
24239
|
const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
|
|
23915
|
-
if (!(0,
|
|
24240
|
+
if (!(0, import_node_fs44.existsSync)(file)) return null;
|
|
23916
24241
|
try {
|
|
23917
|
-
const o = JSON.parse((0,
|
|
24242
|
+
const o = JSON.parse((0, import_node_fs44.readFileSync)(file, "utf-8")) ?? {};
|
|
23918
24243
|
const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
|
|
23919
24244
|
if (isNaN(delivered)) return null;
|
|
23920
24245
|
return {
|
|
@@ -23928,8 +24253,8 @@ function readAdvisoryEpisode(sessionId) {
|
|
|
23928
24253
|
}
|
|
23929
24254
|
function writeAdvisoryEpisode(episode, sessionId) {
|
|
23930
24255
|
try {
|
|
23931
|
-
(0,
|
|
23932
|
-
(0,
|
|
24256
|
+
(0, import_node_fs44.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
24257
|
+
(0, import_node_fs44.writeFileSync)(
|
|
23933
24258
|
scopedFile(ADVISORY_EPISODE_FILE, sessionId),
|
|
23934
24259
|
JSON.stringify({ v: 1, ...episode })
|
|
23935
24260
|
);
|
|
@@ -24237,14 +24562,14 @@ async function buildRequest(run2) {
|
|
|
24237
24562
|
}
|
|
24238
24563
|
|
|
24239
24564
|
// src/lib/offline.ts
|
|
24240
|
-
var
|
|
24565
|
+
var import_node_fs45 = require("node:fs");
|
|
24241
24566
|
var import_node_crypto11 = require("node:crypto");
|
|
24242
24567
|
function cacheRequest(body) {
|
|
24243
24568
|
try {
|
|
24244
|
-
(0,
|
|
24569
|
+
(0, import_node_fs45.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
24245
24570
|
const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
|
|
24246
24571
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
24247
|
-
(0,
|
|
24572
|
+
(0, import_node_fs45.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
|
|
24248
24573
|
} catch {
|
|
24249
24574
|
}
|
|
24250
24575
|
}
|
|
@@ -24363,8 +24688,8 @@ async function transmit(run2) {
|
|
|
24363
24688
|
}
|
|
24364
24689
|
|
|
24365
24690
|
// src/commands/analyze/phases/13-reconcile.ts
|
|
24366
|
-
var
|
|
24367
|
-
var
|
|
24691
|
+
var import_node_fs46 = require("node:fs");
|
|
24692
|
+
var import_node_path35 = require("node:path");
|
|
24368
24693
|
async function reconcile(run2) {
|
|
24369
24694
|
const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
|
|
24370
24695
|
const sentPaths = codeDelta.files.map((f) => f.path);
|
|
@@ -24393,7 +24718,7 @@ async function reconcile(run2) {
|
|
|
24393
24718
|
const st = foldDossier(memorySession.d);
|
|
24394
24719
|
openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
|
|
24395
24720
|
try {
|
|
24396
|
-
const src = (0,
|
|
24721
|
+
const src = (0, import_node_fs46.readFileSync)((0, import_node_path35.join)(repoRoot(), file), "utf8").split("\n");
|
|
24397
24722
|
const at = src[line - 1];
|
|
24398
24723
|
return at === void 0 ? null : lineSha(at);
|
|
24399
24724
|
} catch {
|
|
@@ -24679,12 +25004,20 @@ async function pullRepoMemory(opts) {
|
|
|
24679
25004
|
let version = null;
|
|
24680
25005
|
let cursor = null;
|
|
24681
25006
|
let pages = 0;
|
|
24682
|
-
const remember = (complete) =>
|
|
24683
|
-
|
|
24684
|
-
|
|
24685
|
-
|
|
24686
|
-
|
|
24687
|
-
|
|
25007
|
+
const remember = async (complete) => {
|
|
25008
|
+
const onDisk = await readPullState();
|
|
25009
|
+
const meanwhile = /* @__PURE__ */ new Map();
|
|
25010
|
+
for (const [path, hash] of onDisk.served) {
|
|
25011
|
+
if (state.served.get(path) !== hash) meanwhile.set(path, hash);
|
|
25012
|
+
}
|
|
25013
|
+
await writePullState({
|
|
25014
|
+
version: complete ? version : null,
|
|
25015
|
+
// A complete pull saw every file the server holds, so its ledger replaces
|
|
25016
|
+
// the old one (a path that stopped arriving was archived) — except for what
|
|
25017
|
+
// another writer recorded while it ran. A partial one only adds.
|
|
25018
|
+
served: complete ? new Map([...served, ...meanwhile]) : new Map([...state.served, ...served, ...meanwhile])
|
|
25019
|
+
});
|
|
25020
|
+
};
|
|
24688
25021
|
do {
|
|
24689
25022
|
const params = new URLSearchParams({ limit: String(PAGE_SIZE) });
|
|
24690
25023
|
if (cursor) params.set("cursor", cursor);
|
|
@@ -24757,7 +25090,7 @@ async function readPullState() {
|
|
|
24757
25090
|
async function writePullState(state) {
|
|
24758
25091
|
try {
|
|
24759
25092
|
await (0, import_promises16.mkdir)(projectPath(VERITY_DIR), { recursive: true });
|
|
24760
|
-
await (
|
|
25093
|
+
await writeFileAtomic(pullStateFile(), JSON.stringify({
|
|
24761
25094
|
...state.version ? { version: state.version } : {},
|
|
24762
25095
|
pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24763
25096
|
served: Object.fromEntries(state.served)
|
|
@@ -25200,7 +25533,7 @@ function registerAnalyzeCommand(program2) {
|
|
|
25200
25533
|
var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
|
|
25201
25534
|
async function runAnalyze(opts, globals) {
|
|
25202
25535
|
if (!verityConfigured()) {
|
|
25203
|
-
(0,
|
|
25536
|
+
(0, import_node_fs47.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
|
|
25204
25537
|
process.exit(0);
|
|
25205
25538
|
}
|
|
25206
25539
|
const run2 = createRun(opts, globals);
|
|
@@ -25221,11 +25554,11 @@ async function runAnalyze(opts, globals) {
|
|
|
25221
25554
|
}
|
|
25222
25555
|
|
|
25223
25556
|
// src/commands/baseline.ts
|
|
25224
|
-
var
|
|
25557
|
+
var import_node_fs49 = require("node:fs");
|
|
25225
25558
|
|
|
25226
25559
|
// src/lib/project-skills.ts
|
|
25227
|
-
var
|
|
25228
|
-
var
|
|
25560
|
+
var import_node_fs48 = require("node:fs");
|
|
25561
|
+
var import_node_path36 = require("node:path");
|
|
25229
25562
|
var PROJECT_SKILL_NAMES = [
|
|
25230
25563
|
"verity-setup",
|
|
25231
25564
|
"verity-analyze",
|
|
@@ -25250,14 +25583,14 @@ var LEGACY_SKILL_NAMES = [
|
|
|
25250
25583
|
var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
|
|
25251
25584
|
function staleProjectSkills() {
|
|
25252
25585
|
const root = projectPath(".claude/skills");
|
|
25253
|
-
if (!(0,
|
|
25254
|
-
return ALL.filter((name) => (0,
|
|
25586
|
+
if (!(0, import_node_fs48.existsSync)(root)) return [];
|
|
25587
|
+
return ALL.filter((name) => (0, import_node_fs48.existsSync)((0, import_node_path36.join)(root, name)));
|
|
25255
25588
|
}
|
|
25256
25589
|
function removeProjectSkills() {
|
|
25257
25590
|
const root = projectPath(".claude/skills");
|
|
25258
25591
|
const removed = [];
|
|
25259
25592
|
for (const name of staleProjectSkills()) {
|
|
25260
|
-
(0,
|
|
25593
|
+
(0, import_node_fs48.rmSync)((0, import_node_path36.join)(root, name), { recursive: true, force: true });
|
|
25261
25594
|
removed.push(name);
|
|
25262
25595
|
}
|
|
25263
25596
|
return removed;
|
|
@@ -25285,10 +25618,10 @@ function registerBaselineCommands(program2) {
|
|
|
25285
25618
|
const session = sessionId ?? validSessionId(process.env.CLAUDE_SESSION_ID);
|
|
25286
25619
|
const cli = pluginCliInvocation();
|
|
25287
25620
|
const skew = cliVersionSkew();
|
|
25288
|
-
const why = skew ? `the \`verity\` on PATH is ${skew.global} but
|
|
25621
|
+
const why = skew ? `the \`verity\` on PATH is ${skew.global} but the hooks run ${skew.hooks}, so it is not the CLI they use` : verityOnPath() ? "the `verity` on PATH is a separate install whose version could not be read" : "this machine has no `verity` on PATH \u2014 the plugin carries its own copy";
|
|
25289
25622
|
const cliLine = cli ? `Verity CLI: ${why}. When a Verity skill tells you to run \`verity <args>\`, run \`${cli} <args>\` instead. Everything else about the command is identical.` : null;
|
|
25290
|
-
const skewMsg = skew ? `Verity: your global \`verity\` CLI is ${skew.global} but the
|
|
25291
|
-
const skewNote = skew ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the
|
|
25623
|
+
const skewMsg = skew ? `Verity: your global \`verity\` CLI is ${skew.global} but the hooks run ${skew.hooks}. Fix it before using \`verity\` in a terminal: ${skew.remedy}` : null;
|
|
25624
|
+
const skewNote = skew ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the hooks run ${skew.hooks}, and \`${skew.remedy}\` fixes it. Until they have, do not send them to run \`verity login\` in a terminal: that runs the global one, which can sign this machine in to a different server.` : null;
|
|
25292
25625
|
if (!verityConfigured()) {
|
|
25293
25626
|
const how = isPluginInvocation() ? "Tell the user to run /verity:init \u2014 they type it; you cannot invoke it." : "Tell the user to run `verity init` in their terminal.";
|
|
25294
25627
|
const lines = [
|
|
@@ -25322,13 +25655,13 @@ function registerBaselineCommands(program2) {
|
|
|
25322
25655
|
let memoryMsg = null;
|
|
25323
25656
|
let memoryAgentLine = null;
|
|
25324
25657
|
const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
|
|
25325
|
-
if (realStart && !(0,
|
|
25658
|
+
if (realStart && !(0, import_node_fs49.existsSync)(memoryNotice)) {
|
|
25326
25659
|
const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
|
|
25327
25660
|
if (trackedGraph > 0) {
|
|
25328
25661
|
memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
|
|
25329
25662
|
memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
|
|
25330
25663
|
try {
|
|
25331
|
-
(0,
|
|
25664
|
+
(0, import_node_fs49.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
|
|
25332
25665
|
} catch {
|
|
25333
25666
|
}
|
|
25334
25667
|
}
|
|
@@ -25429,7 +25762,7 @@ function hookSource(value) {
|
|
|
25429
25762
|
}
|
|
25430
25763
|
|
|
25431
25764
|
// src/commands/review.ts
|
|
25432
|
-
var
|
|
25765
|
+
var import_node_fs50 = require("node:fs");
|
|
25433
25766
|
function registerReviewCommand(program2) {
|
|
25434
25767
|
program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars)").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
|
|
25435
25768
|
const globals = program2.opts();
|
|
@@ -25446,45 +25779,22 @@ async function runReview(opts, globals) {
|
|
|
25446
25779
|
const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
|
|
25447
25780
|
const analyzable = filterAnalyzable(allFiles);
|
|
25448
25781
|
const securityFiles = filterSecurity(allFiles);
|
|
25449
|
-
|
|
25450
|
-
|
|
25451
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs48.existsSync)(f) || resolveFile(f) !== null);
|
|
25452
|
-
staticResults = runCodacyAnalysis(scannable);
|
|
25453
|
-
} else {
|
|
25454
|
-
staticResults = {
|
|
25455
|
-
tool: "@codacy/analysis-cli",
|
|
25456
|
-
findings: [],
|
|
25457
|
-
summary: { total_findings: 0, by_severity: {}, tools_run: [] }
|
|
25458
|
-
};
|
|
25459
|
-
}
|
|
25782
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs50.existsSync)(f) || resolveFile(f) !== null);
|
|
25783
|
+
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
25460
25784
|
const codeDelta = collectCodeDelta(allFiles);
|
|
25461
25785
|
const tokenResult = await resolveToken(globals.token);
|
|
25462
25786
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
25463
25787
|
if (!tokenResult.ok || !urlResult.ok) {
|
|
25788
|
+
const staticFailure = staticResults.summary.failure;
|
|
25464
25789
|
printJsonCompact({
|
|
25465
|
-
gate_decision: "
|
|
25466
|
-
systemMessage: "Verity: not authenticated \u2014 showing local static results only (no deep review, no upload). Run `verity init` to authenticate and unlock the full review.",
|
|
25790
|
+
gate_decision: "WARN",
|
|
25791
|
+
systemMessage: staticFailure ? `Verity: not authenticated, and local static analysis did not run (${staticFailure.kind}) \u2014 nothing was examined. Run \`verity init\` to authenticate and unlock the full review.` : "Verity: not authenticated \u2014 showing local static results only (no deep review, no upload). Run `verity init` to authenticate and unlock the full review.",
|
|
25467
25792
|
unauthenticated: true,
|
|
25468
25793
|
static_results: staticResults
|
|
25469
25794
|
});
|
|
25470
25795
|
process.exit(0);
|
|
25471
25796
|
}
|
|
25472
|
-
|
|
25473
|
-
if (opts.specs) {
|
|
25474
|
-
const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
|
|
25475
|
-
specs = [];
|
|
25476
|
-
for (const p of specPaths) {
|
|
25477
|
-
if (!(0, import_node_fs48.existsSync)(p)) continue;
|
|
25478
|
-
try {
|
|
25479
|
-
const { readFileSync: readFileSync26 } = await import("node:fs");
|
|
25480
|
-
const content = readFileSync26(p, "utf-8");
|
|
25481
|
-
specs.push({ path: p, content: content.slice(0, 10240) });
|
|
25482
|
-
} catch {
|
|
25483
|
-
}
|
|
25484
|
-
}
|
|
25485
|
-
} else {
|
|
25486
|
-
specs = discoverSpecs();
|
|
25487
|
-
}
|
|
25797
|
+
const specs = opts.specs ? readSpecFiles(opts.specs, repoRoot()) : discoverSpecs();
|
|
25488
25798
|
const plans = discoverPlans();
|
|
25489
25799
|
const requestBody = {
|
|
25490
25800
|
static_results: staticResults,
|
|
@@ -25517,9 +25827,10 @@ async function runReview(opts, globals) {
|
|
|
25517
25827
|
});
|
|
25518
25828
|
if (!result.ok) {
|
|
25519
25829
|
printError(`Service error: ${result.error}`);
|
|
25830
|
+
const staticFailure = staticResults.summary.failure;
|
|
25520
25831
|
printJsonCompact({
|
|
25521
|
-
gate_decision: "
|
|
25522
|
-
systemMessage: "Verity:
|
|
25832
|
+
gate_decision: "WARN",
|
|
25833
|
+
systemMessage: staticFailure ? `Verity: service unavailable, and local static analysis did not run (${staticFailure.kind}) \u2014 nothing was examined` : "Verity: service unavailable \u2014 showing local static results only",
|
|
25523
25834
|
offline: true,
|
|
25524
25835
|
static_results: staticResults
|
|
25525
25836
|
});
|
|
@@ -25534,8 +25845,8 @@ async function runReview(opts, globals) {
|
|
|
25534
25845
|
}
|
|
25535
25846
|
|
|
25536
25847
|
// src/commands/guard.ts
|
|
25537
|
-
var
|
|
25538
|
-
var
|
|
25848
|
+
var import_node_fs51 = require("node:fs");
|
|
25849
|
+
var import_node_path37 = require("node:path");
|
|
25539
25850
|
|
|
25540
25851
|
// src/lib/terminal-text.ts
|
|
25541
25852
|
var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
|
|
@@ -25910,7 +26221,7 @@ async function buildAgentDiffs(ctx, paths, limits = { perFileChars: 24e3, totalC
|
|
|
25910
26221
|
// src/commands/guard.ts
|
|
25911
26222
|
var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
25912
26223
|
var GUARD_BLOCK_CAP = 2;
|
|
25913
|
-
var GUARD_ITER_FILE = (0,
|
|
26224
|
+
var GUARD_ITER_FILE = (0, import_node_path37.join)(VERITY_DIR, ".guard-iteration");
|
|
25914
26225
|
function readPreToolUseStdin() {
|
|
25915
26226
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
25916
26227
|
return new Promise((resolve6) => {
|
|
@@ -25955,7 +26266,7 @@ function readPreToolUseStdin() {
|
|
|
25955
26266
|
}
|
|
25956
26267
|
function readIterMap() {
|
|
25957
26268
|
try {
|
|
25958
|
-
const raw = JSON.parse((0,
|
|
26269
|
+
const raw = JSON.parse((0, import_node_fs51.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
25959
26270
|
if (raw && typeof raw === "object") {
|
|
25960
26271
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
25961
26272
|
return { [raw.moment]: raw.count };
|
|
@@ -25975,10 +26286,10 @@ function readIter(moment) {
|
|
|
25975
26286
|
}
|
|
25976
26287
|
function writeIter(moment, count) {
|
|
25977
26288
|
try {
|
|
25978
|
-
(0,
|
|
26289
|
+
(0, import_node_fs51.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
25979
26290
|
const map = readIterMap();
|
|
25980
26291
|
map[moment] = count;
|
|
25981
|
-
(0,
|
|
26292
|
+
(0, import_node_fs51.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
25982
26293
|
} catch {
|
|
25983
26294
|
}
|
|
25984
26295
|
}
|
|
@@ -25988,10 +26299,10 @@ function resetIter(moment) {
|
|
|
25988
26299
|
if (!(moment in map)) return;
|
|
25989
26300
|
delete map[moment];
|
|
25990
26301
|
if (Object.keys(map).length === 0) {
|
|
25991
|
-
if ((0,
|
|
26302
|
+
if ((0, import_node_fs51.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs51.unlinkSync)(GUARD_ITER_FILE);
|
|
25992
26303
|
} else {
|
|
25993
|
-
(0,
|
|
25994
|
-
(0,
|
|
26304
|
+
(0, import_node_fs51.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
26305
|
+
(0, import_node_fs51.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
25995
26306
|
}
|
|
25996
26307
|
} catch {
|
|
25997
26308
|
}
|
|
@@ -26061,13 +26372,8 @@ function hasBlockingFinding(response, sentFiles) {
|
|
|
26061
26372
|
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
26062
26373
|
const analyzable = filterAnalyzable(files);
|
|
26063
26374
|
const securityFiles = filterSecurity(files);
|
|
26064
|
-
|
|
26065
|
-
|
|
26066
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs49.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
26067
|
-
staticResults = runCodacyAnalysis(scannable);
|
|
26068
|
-
} else {
|
|
26069
|
-
staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
|
|
26070
|
-
}
|
|
26375
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs51.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
26376
|
+
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
26071
26377
|
const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
|
|
26072
26378
|
const requestBody = {
|
|
26073
26379
|
static_results: staticResults,
|
|
@@ -26143,6 +26449,9 @@ function worstGate(...gates) {
|
|
|
26143
26449
|
};
|
|
26144
26450
|
return GATES[Math.max(...gates.map(rank2))];
|
|
26145
26451
|
}
|
|
26452
|
+
function oneShotLostOutcome(input) {
|
|
26453
|
+
return input.agentGate === "FAIL" && input.agentBlocking ? "block" : "allow-without-review";
|
|
26454
|
+
}
|
|
26146
26455
|
function withAgentVerdict(oneShot, agent) {
|
|
26147
26456
|
if (agent.one_shot_source === "none" && typeof oneShot.gate_decision === "string") {
|
|
26148
26457
|
const added = agent.findings.filter((f) => f.agent_added === true);
|
|
@@ -26311,6 +26620,7 @@ async function runGuard(opts, globals) {
|
|
|
26311
26620
|
symbols: repoContext2.symbols?.length ?? 0,
|
|
26312
26621
|
callers: repoContext2.callers?.length ?? 0,
|
|
26313
26622
|
tests: repoContext2.tests?.length ?? 0,
|
|
26623
|
+
importers: repoContext2.importers?.length ?? 0,
|
|
26314
26624
|
excerpts: repoContext2.excerpts?.length ?? 0,
|
|
26315
26625
|
elapsed_ms: repoContext2.elapsed_ms ?? null
|
|
26316
26626
|
});
|
|
@@ -26357,13 +26667,6 @@ async function runGuard(opts, globals) {
|
|
|
26357
26667
|
const agentOutcome = agent ? await agent : null;
|
|
26358
26668
|
const agentVerdict = agentOutcome?.kind === "finished" && agentOutcome.response.gate_decision ? agentOutcome.response : null;
|
|
26359
26669
|
const reviewSecs = Math.max(1, Math.round((Date.now() - reviewStart) / 1e3));
|
|
26360
|
-
if (!result.ok && !agentVerdict) {
|
|
26361
|
-
const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
|
|
26362
|
-
emitAllowNotice(
|
|
26363
|
-
`\u26A0 Verity ${moment}: ${authRemedy ? "not authorized" : "service offline"} \u2014 ${verb}ed WITHOUT review${authRemedy}`,
|
|
26364
|
-
`Verity ${moment}: ${authRemedy ? "not authorized" : "service unavailable"} (${result.error}); the ${verb} was allowed WITHOUT a Verity review.${authRemedy}`
|
|
26365
|
-
);
|
|
26366
|
-
}
|
|
26367
26670
|
const oneShotResponse = result.ok ? result.data : {};
|
|
26368
26671
|
const response = agentVerdict ? withAgentVerdict(oneShotResponse, agentVerdict) : oneShotResponse;
|
|
26369
26672
|
if (opts.json) process.stderr.write(JSON.stringify(response) + "\n");
|
|
@@ -26375,6 +26678,19 @@ async function runGuard(opts, globals) {
|
|
|
26375
26678
|
const covDetail = agentLine ? `${coverageBlock(coverage)}
|
|
26376
26679
|
${agentLine}` : coverageBlock(coverage);
|
|
26377
26680
|
const witnessed = [...codeDelta.files.map((f) => f.path), ...agentVerdict?.witnessed_files ?? []];
|
|
26681
|
+
if (!result.ok) {
|
|
26682
|
+
const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
|
|
26683
|
+
if (oneShotLostOutcome({ agentGate: decision, agentBlocking: hasBlockingFinding(response, witnessed) }) === "block") {
|
|
26684
|
+
writeIter(moment, iter + 1);
|
|
26685
|
+
writeBlockMessage(moment, response, covDetail);
|
|
26686
|
+
process.exit(2);
|
|
26687
|
+
}
|
|
26688
|
+
const agentNote = agentLine ? ` ${agentLine}, but it reviewed only part of the change.` : "";
|
|
26689
|
+
emitAllowNotice(
|
|
26690
|
+
`\u26A0 Verity ${moment}: ${authRemedy ? "not authorized" : "no single-pass review"} \u2014 ${verb}ed WITHOUT review${authRemedy}`,
|
|
26691
|
+
`Verity ${moment}: the single-pass review did not come back (${result.error}); the ${verb} was allowed WITHOUT a Verity review.${agentNote}${authRemedy}`
|
|
26692
|
+
);
|
|
26693
|
+
}
|
|
26378
26694
|
if (decision === "FAIL" && hasBlockingFinding(response, witnessed)) {
|
|
26379
26695
|
writeIter(moment, iter + 1);
|
|
26380
26696
|
writeBlockMessage(moment, response, covDetail);
|
|
@@ -26566,7 +26882,7 @@ function registerIgnoreCommand(program2) {
|
|
|
26566
26882
|
|
|
26567
26883
|
// src/commands/waive.ts
|
|
26568
26884
|
var import_node_crypto12 = require("node:crypto");
|
|
26569
|
-
var
|
|
26885
|
+
var import_node_fs52 = require("node:fs");
|
|
26570
26886
|
function registerWaiveCommand(program2) {
|
|
26571
26887
|
program2.command("waive <pattern-id>").description("Record an accepted-risk disposition for an open finding (voids when the file changes)").option("--file <path>", "File the finding is anchored to, REPO-RELATIVE (recommended \u2014 narrows the waive)").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action(async (patternId, opts) => {
|
|
26572
26888
|
const globals = program2.opts();
|
|
@@ -26595,7 +26911,7 @@ function registerWaiveCommand(program2) {
|
|
|
26595
26911
|
if (opts.file) {
|
|
26596
26912
|
body.file = opts.file;
|
|
26597
26913
|
try {
|
|
26598
|
-
body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0,
|
|
26914
|
+
body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs52.readFileSync)(opts.file)).digest("hex");
|
|
26599
26915
|
} catch {
|
|
26600
26916
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
26601
26917
|
process.exit(1);
|
|
@@ -26620,10 +26936,10 @@ function registerWaiveCommand(program2) {
|
|
|
26620
26936
|
}
|
|
26621
26937
|
|
|
26622
26938
|
// src/commands/init.ts
|
|
26623
|
-
var
|
|
26939
|
+
var import_node_fs56 = require("node:fs");
|
|
26624
26940
|
var import_promises19 = require("node:fs/promises");
|
|
26625
26941
|
var import_yaml6 = __toESM(require_dist());
|
|
26626
|
-
var
|
|
26942
|
+
var import_node_path40 = require("node:path");
|
|
26627
26943
|
var import_node_child_process17 = require("node:child_process");
|
|
26628
26944
|
|
|
26629
26945
|
// src/lib/banner.ts
|
|
@@ -26702,18 +27018,13 @@ function printPhase(n, of, title, subtitle) {
|
|
|
26702
27018
|
}
|
|
26703
27019
|
|
|
26704
27020
|
// src/commands/doctor.ts
|
|
26705
|
-
var
|
|
27021
|
+
var import_node_fs53 = require("node:fs");
|
|
26706
27022
|
|
|
26707
27023
|
// src/lib/prereqs.ts
|
|
26708
27024
|
var import_node_child_process15 = require("node:child_process");
|
|
26709
27025
|
var MIN_NODE_MAJOR = 20;
|
|
26710
27026
|
function which(bin) {
|
|
26711
|
-
|
|
26712
|
-
const out = (0, import_node_child_process15.execSync)(`command -v ${bin}`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
26713
|
-
return out || null;
|
|
26714
|
-
} catch {
|
|
26715
|
-
return null;
|
|
26716
|
-
}
|
|
27027
|
+
return whichSync(bin, { real: false });
|
|
26717
27028
|
}
|
|
26718
27029
|
function checkNode() {
|
|
26719
27030
|
const version = process.version;
|
|
@@ -26913,12 +27224,13 @@ async function buildReport() {
|
|
|
26913
27224
|
const state = await readSetupState();
|
|
26914
27225
|
const wiring = await resolveHookWiring();
|
|
26915
27226
|
const hooks = wiring.status;
|
|
27227
|
+
const provenance = cliProvenance();
|
|
26916
27228
|
const telemetry = await checkTelemetry();
|
|
26917
|
-
const hasConfig = (0,
|
|
27229
|
+
const hasConfig = (0, import_node_fs53.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
26918
27230
|
const artifacts = {
|
|
26919
|
-
standard: (0,
|
|
27231
|
+
standard: (0, import_node_fs53.existsSync)(projectPath(STANDARD_FILE)),
|
|
26920
27232
|
analysisConfig: hasConfig,
|
|
26921
|
-
verityMd: (0,
|
|
27233
|
+
verityMd: (0, import_node_fs53.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
26922
27234
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
26923
27235
|
};
|
|
26924
27236
|
const next = [];
|
|
@@ -26956,6 +27268,12 @@ async function buildReport() {
|
|
|
26956
27268
|
'Duplicate Verity hooks also exist in .claude/settings.json. They stand down at run time under the plugin, but remove them with "verity init --plugin-mode" so the wiring says what it does.'
|
|
26957
27269
|
);
|
|
26958
27270
|
}
|
|
27271
|
+
const versions = versionReport(provenance);
|
|
27272
|
+
if (provenance.skew) {
|
|
27273
|
+
next.push(
|
|
27274
|
+
`The \`verity\` on PATH is ${provenance.skew.global}, but the plugin's hooks run ${provenance.skew.hooks} \u2014 so the gate and your terminal are different builds. Fix: ${provenance.skew.remedy}.`
|
|
27275
|
+
);
|
|
27276
|
+
}
|
|
26959
27277
|
if (state?.telemetry === "deferred") {
|
|
26960
27278
|
next.push('Telemetry was requested but needs a token \u2014 run "verity login", then "verity telemetry install".');
|
|
26961
27279
|
}
|
|
@@ -26993,7 +27311,8 @@ async function buildReport() {
|
|
|
26993
27311
|
source: wiring.source,
|
|
26994
27312
|
...hooks,
|
|
26995
27313
|
duplicateSettingsHooks: wiring.duplicateSettingsHooks,
|
|
26996
|
-
noAnalysisMoment
|
|
27314
|
+
noAnalysisMoment,
|
|
27315
|
+
versions
|
|
26997
27316
|
},
|
|
26998
27317
|
telemetry: { enabled: telemetry.enabled, endpoint: telemetry.endpoint },
|
|
26999
27318
|
artifacts,
|
|
@@ -27024,6 +27343,9 @@ function registerDoctorCommand(program2) {
|
|
|
27024
27343
|
printInfo(` intensity: ${report.answers.intensity ?? "\u2014"} moments: ${report.answers.moments?.join(", ") ?? "\u2014"}`);
|
|
27025
27344
|
const plugin = report.hooks.source === "plugin";
|
|
27026
27345
|
printInfo(plugin ? "Hooks: wired by the Verity Claude Code plugin (not .claude/settings.json)" : "Hooks:");
|
|
27346
|
+
const versionOut = versionLines(report.hooks.versions);
|
|
27347
|
+
for (const line of versionOut.info) printInfo(line);
|
|
27348
|
+
for (const line of versionOut.warn) printWarn(line);
|
|
27027
27349
|
printInfo(` Stop (verity analyze): ${report.hooks.stop ? plugin ? "on (plugin)" : "on" : "off"}`);
|
|
27028
27350
|
printInfo(` Git-moment gate: ${report.hooks.guardOn.length ? report.hooks.guardOn.join(", ") : "off"}`);
|
|
27029
27351
|
printInfo(` Infra (intent/baseline/compact/session-end): ${[report.hooks.intent, report.hooks.baseline, report.hooks.compact, report.hooks.sessionEnd].filter(Boolean).length}/4`);
|
|
@@ -27049,8 +27371,8 @@ function registerDoctorCommand(program2) {
|
|
|
27049
27371
|
}
|
|
27050
27372
|
|
|
27051
27373
|
// src/commands/migrate.ts
|
|
27052
|
-
var
|
|
27053
|
-
var
|
|
27374
|
+
var import_node_fs54 = require("node:fs");
|
|
27375
|
+
var import_node_path38 = require("node:path");
|
|
27054
27376
|
var import_node_child_process16 = require("node:child_process");
|
|
27055
27377
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
27056
27378
|
function defaultNpmRemover(pkg) {
|
|
@@ -27087,12 +27409,12 @@ async function runMigration(opts = {}) {
|
|
|
27087
27409
|
return { actions, migrated: actions.length > 0 };
|
|
27088
27410
|
}
|
|
27089
27411
|
function migrateProjectDir(root, actions) {
|
|
27090
|
-
const gateDir = (0,
|
|
27091
|
-
const verityDir = (0,
|
|
27092
|
-
if ((0,
|
|
27412
|
+
const gateDir = (0, import_node_path38.join)(root, ".gate");
|
|
27413
|
+
const verityDir = (0, import_node_path38.join)(root, ".verity");
|
|
27414
|
+
if ((0, import_node_fs54.existsSync)(gateDir) && !(0, import_node_fs54.existsSync)(verityDir)) {
|
|
27093
27415
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
27094
27416
|
}
|
|
27095
|
-
if ((0,
|
|
27417
|
+
if ((0, import_node_fs54.existsSync)(gateDir) && (0, import_node_fs54.existsSync)(verityDir)) {
|
|
27096
27418
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
27097
27419
|
}
|
|
27098
27420
|
return false;
|
|
@@ -27113,13 +27435,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
27113
27435
|
}
|
|
27114
27436
|
}
|
|
27115
27437
|
if (moved) {
|
|
27116
|
-
if ((0,
|
|
27438
|
+
if ((0, import_node_fs54.existsSync)(gateDir)) {
|
|
27117
27439
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
27118
27440
|
if (carried > 0) {
|
|
27119
27441
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
27120
27442
|
}
|
|
27121
27443
|
try {
|
|
27122
|
-
(0,
|
|
27444
|
+
(0, import_node_fs54.rmSync)(gateDir, { recursive: true, force: true });
|
|
27123
27445
|
} catch {
|
|
27124
27446
|
}
|
|
27125
27447
|
}
|
|
@@ -27135,18 +27457,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
27135
27457
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
27136
27458
|
}
|
|
27137
27459
|
try {
|
|
27138
|
-
(0,
|
|
27460
|
+
(0, import_node_fs54.rmSync)(gateDir, { recursive: true, force: true });
|
|
27139
27461
|
} catch {
|
|
27140
27462
|
}
|
|
27141
27463
|
return carried > 0;
|
|
27142
27464
|
}
|
|
27143
27465
|
function migrateGlobalCredentials(home, actions) {
|
|
27144
27466
|
if (!home) return;
|
|
27145
|
-
const gateCreds = (0,
|
|
27146
|
-
const verityCreds = (0,
|
|
27147
|
-
if (!(0,
|
|
27148
|
-
if (!(0,
|
|
27149
|
-
(0,
|
|
27467
|
+
const gateCreds = (0, import_node_path38.join)(home, ".gate", "credentials");
|
|
27468
|
+
const verityCreds = (0, import_node_path38.join)(home, ".verity", "credentials");
|
|
27469
|
+
if (!(0, import_node_fs54.existsSync)(gateCreds)) return;
|
|
27470
|
+
if (!(0, import_node_fs54.existsSync)(verityCreds)) {
|
|
27471
|
+
(0, import_node_fs54.mkdirSync)((0, import_node_path38.join)(home, ".verity"), { recursive: true });
|
|
27150
27472
|
moveFile(gateCreds, verityCreds);
|
|
27151
27473
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
27152
27474
|
return;
|
|
@@ -27168,8 +27490,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
27168
27490
|
}
|
|
27169
27491
|
}
|
|
27170
27492
|
async function migrateClaudeMd(root, actions) {
|
|
27171
|
-
const claudeMd = (0,
|
|
27172
|
-
const hadLegacyBlock = (0,
|
|
27493
|
+
const claudeMd = (0, import_node_path38.join)(root, "CLAUDE.md");
|
|
27494
|
+
const hadLegacyBlock = (0, import_node_fs54.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
27173
27495
|
if (!hadLegacyBlock) return;
|
|
27174
27496
|
try {
|
|
27175
27497
|
await ensureClaudeMdPointer(root);
|
|
@@ -27179,9 +27501,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
27179
27501
|
}
|
|
27180
27502
|
}
|
|
27181
27503
|
function migrateStandardFile(root, actions) {
|
|
27182
|
-
const gateMd = (0,
|
|
27183
|
-
const verityMd = (0,
|
|
27184
|
-
if (!(0,
|
|
27504
|
+
const gateMd = (0, import_node_path38.join)(root, "GATE.md");
|
|
27505
|
+
const verityMd = (0, import_node_path38.join)(root, "VERITY.md");
|
|
27506
|
+
if (!(0, import_node_fs54.existsSync)(gateMd) || (0, import_node_fs54.existsSync)(verityMd)) return;
|
|
27185
27507
|
let moved = false;
|
|
27186
27508
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
27187
27509
|
try {
|
|
@@ -27193,12 +27515,12 @@ function migrateStandardFile(root, actions) {
|
|
|
27193
27515
|
if (!moved) moveFile(gateMd, verityMd);
|
|
27194
27516
|
const content = readFileSyncSafe(verityMd);
|
|
27195
27517
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
27196
|
-
if (refreshed !== content) (0,
|
|
27518
|
+
if (refreshed !== content) (0, import_node_fs54.writeFileSync)(verityMd, refreshed);
|
|
27197
27519
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
27198
27520
|
}
|
|
27199
27521
|
async function migrateTelemetryHeaders(root, actions) {
|
|
27200
|
-
const file = (0,
|
|
27201
|
-
if (!(0,
|
|
27522
|
+
const file = (0, import_node_path38.join)(root, ".claude", "settings.local.json");
|
|
27523
|
+
if (!(0, import_node_fs54.existsSync)(file)) return;
|
|
27202
27524
|
let settings;
|
|
27203
27525
|
try {
|
|
27204
27526
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -27246,14 +27568,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
27246
27568
|
}
|
|
27247
27569
|
if (toAppend.length > 0) {
|
|
27248
27570
|
const sep4 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
27249
|
-
(0,
|
|
27571
|
+
(0, import_node_fs54.writeFileSync)(verityCreds, verityContent + sep4 + toAppend.join("\n") + "\n");
|
|
27250
27572
|
}
|
|
27251
|
-
(0,
|
|
27573
|
+
(0, import_node_fs54.rmSync)(gateCreds, { force: true });
|
|
27252
27574
|
return toAppend.length;
|
|
27253
27575
|
}
|
|
27254
27576
|
function readFileSyncSafe(path) {
|
|
27255
27577
|
try {
|
|
27256
|
-
return (0,
|
|
27578
|
+
return (0, import_node_fs54.readFileSync)(path, "utf-8");
|
|
27257
27579
|
} catch {
|
|
27258
27580
|
return "";
|
|
27259
27581
|
}
|
|
@@ -27268,35 +27590,35 @@ function hasStagedChanges(root) {
|
|
|
27268
27590
|
}
|
|
27269
27591
|
function moveDir(from, to) {
|
|
27270
27592
|
try {
|
|
27271
|
-
(0,
|
|
27593
|
+
(0, import_node_fs54.renameSync)(from, to);
|
|
27272
27594
|
} catch (err) {
|
|
27273
27595
|
if (err.code !== "EXDEV") throw err;
|
|
27274
|
-
(0,
|
|
27275
|
-
(0,
|
|
27596
|
+
(0, import_node_fs54.cpSync)(from, to, { recursive: true });
|
|
27597
|
+
(0, import_node_fs54.rmSync)(from, { recursive: true, force: true });
|
|
27276
27598
|
}
|
|
27277
27599
|
}
|
|
27278
27600
|
function moveFile(from, to) {
|
|
27279
27601
|
try {
|
|
27280
|
-
(0,
|
|
27602
|
+
(0, import_node_fs54.renameSync)(from, to);
|
|
27281
27603
|
} catch (err) {
|
|
27282
27604
|
if (err.code !== "EXDEV") throw err;
|
|
27283
|
-
(0,
|
|
27284
|
-
(0,
|
|
27605
|
+
(0, import_node_fs54.cpSync)(from, to);
|
|
27606
|
+
(0, import_node_fs54.rmSync)(from, { force: true });
|
|
27285
27607
|
}
|
|
27286
27608
|
}
|
|
27287
27609
|
function carryLegacyContents(gateDir, verityDir) {
|
|
27288
27610
|
let copied = 0;
|
|
27289
27611
|
const walk2 = (relDir) => {
|
|
27290
|
-
const srcDir = (0,
|
|
27291
|
-
for (const entry of (0,
|
|
27292
|
-
const rel = relDir ? (0,
|
|
27293
|
-
const src = (0,
|
|
27294
|
-
const dest = (0,
|
|
27295
|
-
if ((0,
|
|
27612
|
+
const srcDir = (0, import_node_path38.join)(gateDir, relDir);
|
|
27613
|
+
for (const entry of (0, import_node_fs54.readdirSync)(srcDir)) {
|
|
27614
|
+
const rel = relDir ? (0, import_node_path38.join)(relDir, entry) : entry;
|
|
27615
|
+
const src = (0, import_node_path38.join)(gateDir, rel);
|
|
27616
|
+
const dest = (0, import_node_path38.join)(verityDir, rel);
|
|
27617
|
+
if ((0, import_node_fs54.statSync)(src).isDirectory()) {
|
|
27296
27618
|
walk2(rel);
|
|
27297
|
-
} else if (!(0,
|
|
27298
|
-
(0,
|
|
27299
|
-
(0,
|
|
27619
|
+
} else if (!(0, import_node_fs54.existsSync)(dest)) {
|
|
27620
|
+
(0, import_node_fs54.mkdirSync)((0, import_node_path38.dirname)(dest), { recursive: true });
|
|
27621
|
+
(0, import_node_fs54.cpSync)(src, dest);
|
|
27300
27622
|
copied++;
|
|
27301
27623
|
}
|
|
27302
27624
|
}
|
|
@@ -27305,22 +27627,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
27305
27627
|
return copied;
|
|
27306
27628
|
}
|
|
27307
27629
|
async function needsMigration(root = repoRoot()) {
|
|
27308
|
-
const gateDir = (0,
|
|
27309
|
-
const verityDir = (0,
|
|
27310
|
-
if ((0,
|
|
27311
|
-
if ((0,
|
|
27312
|
-
if ((0,
|
|
27630
|
+
const gateDir = (0, import_node_path38.join)(root, ".gate");
|
|
27631
|
+
const verityDir = (0, import_node_path38.join)(root, ".verity");
|
|
27632
|
+
if ((0, import_node_fs54.existsSync)(gateDir) && !(0, import_node_fs54.existsSync)(verityDir)) return true;
|
|
27633
|
+
if ((0, import_node_fs54.existsSync)(gateDir) && (0, import_node_fs54.existsSync)(verityDir)) {
|
|
27634
|
+
if ((0, import_node_fs54.existsSync)((0, import_node_path38.join)(gateDir, "credentials")) && !(0, import_node_fs54.existsSync)((0, import_node_path38.join)(verityDir, "credentials"))) {
|
|
27313
27635
|
return true;
|
|
27314
27636
|
}
|
|
27315
|
-
if ((0,
|
|
27637
|
+
if ((0, import_node_fs54.existsSync)((0, import_node_path38.join)(gateDir, "memory")) && !(0, import_node_fs54.existsSync)((0, import_node_path38.join)(verityDir, "memory"))) {
|
|
27316
27638
|
return true;
|
|
27317
27639
|
}
|
|
27318
27640
|
}
|
|
27319
|
-
const claudeMd = (0,
|
|
27320
|
-
if ((0,
|
|
27641
|
+
const claudeMd = (0, import_node_path38.join)(root, "CLAUDE.md");
|
|
27642
|
+
if ((0, import_node_fs54.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
27321
27643
|
return true;
|
|
27322
27644
|
}
|
|
27323
|
-
if ((0,
|
|
27645
|
+
if ((0, import_node_fs54.existsSync)((0, import_node_path38.join)(root, "GATE.md")) && !(0, import_node_fs54.existsSync)((0, import_node_path38.join)(root, "VERITY.md"))) {
|
|
27324
27646
|
return true;
|
|
27325
27647
|
}
|
|
27326
27648
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -27601,9 +27923,9 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
27601
27923
|
}
|
|
27602
27924
|
|
|
27603
27925
|
// src/lib/remote-config.ts
|
|
27604
|
-
var
|
|
27926
|
+
var import_node_fs55 = require("node:fs");
|
|
27605
27927
|
var import_promises18 = require("node:fs/promises");
|
|
27606
|
-
var
|
|
27928
|
+
var import_node_path39 = require("node:path");
|
|
27607
27929
|
var import_yaml5 = __toESM(require_dist());
|
|
27608
27930
|
var IGNORE_RIDER = "verityignore";
|
|
27609
27931
|
async function fetchRemoteSetup(opts) {
|
|
@@ -27648,7 +27970,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
27648
27970
|
written.push(STANDARD_FILE);
|
|
27649
27971
|
if (rider !== null) {
|
|
27650
27972
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
27651
|
-
if (!(0,
|
|
27973
|
+
if (!(0, import_node_fs55.existsSync)(localIgnore)) {
|
|
27652
27974
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
27653
27975
|
written.push(VERITYIGNORE_FILE);
|
|
27654
27976
|
} else {
|
|
@@ -27679,9 +28001,9 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
27679
28001
|
written.push(VERITY_MD_FILE);
|
|
27680
28002
|
return { written, notes };
|
|
27681
28003
|
}
|
|
27682
|
-
async function writeOut(
|
|
27683
|
-
const target = projectPath(
|
|
27684
|
-
await (0, import_promises18.mkdir)((0,
|
|
28004
|
+
async function writeOut(relative3, body) {
|
|
28005
|
+
const target = projectPath(relative3);
|
|
28006
|
+
await (0, import_promises18.mkdir)((0, import_node_path39.dirname)(target), { recursive: true });
|
|
27685
28007
|
await (0, import_promises18.writeFile)(target, body);
|
|
27686
28008
|
}
|
|
27687
28009
|
function describeRemote(found) {
|
|
@@ -27798,15 +28120,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
27798
28120
|
}
|
|
27799
28121
|
function resolveDataDir2() {
|
|
27800
28122
|
const candidates2 = [
|
|
27801
|
-
(0,
|
|
28123
|
+
(0, import_node_path40.join)(__dirname, "..", "data"),
|
|
27802
28124
|
// installed: node_modules/@codacy/verity-cli/data
|
|
27803
|
-
(0,
|
|
28125
|
+
(0, import_node_path40.join)(__dirname, "..", "..", "data"),
|
|
27804
28126
|
// edge case: nested resolution
|
|
27805
|
-
(0,
|
|
28127
|
+
(0, import_node_path40.join)(process.cwd(), "cli", "data")
|
|
27806
28128
|
// local dev: running from repo root
|
|
27807
28129
|
];
|
|
27808
28130
|
for (const candidate of candidates2) {
|
|
27809
|
-
if ((0,
|
|
28131
|
+
if ((0, import_node_fs56.existsSync)((0, import_node_path40.join)(candidate, "skills"))) {
|
|
27810
28132
|
return candidate;
|
|
27811
28133
|
}
|
|
27812
28134
|
}
|
|
@@ -27822,9 +28144,9 @@ async function skillIsCurrent(src, dest) {
|
|
|
27822
28144
|
const list2 = (dir) => {
|
|
27823
28145
|
const out = [];
|
|
27824
28146
|
const walk2 = (d, prefix) => {
|
|
27825
|
-
for (const e of (0,
|
|
28147
|
+
for (const e of (0, import_node_fs56.readdirSync)(d, { withFileTypes: true })) {
|
|
27826
28148
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
27827
|
-
if (e.isDirectory()) walk2((0,
|
|
28149
|
+
if (e.isDirectory()) walk2((0, import_node_path40.join)(d, e.name), rel);
|
|
27828
28150
|
else if (e.isFile()) out.push(rel);
|
|
27829
28151
|
}
|
|
27830
28152
|
};
|
|
@@ -27835,8 +28157,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
27835
28157
|
const shipped = list2(src);
|
|
27836
28158
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
27837
28159
|
for (const rel of shipped) {
|
|
27838
|
-
const a = await (0, import_promises19.readFile)((0,
|
|
27839
|
-
const b = await (0, import_promises19.readFile)((0,
|
|
28160
|
+
const a = await (0, import_promises19.readFile)((0, import_node_path40.join)(src, rel), "utf-8");
|
|
28161
|
+
const b = await (0, import_promises19.readFile)((0, import_node_path40.join)(dest, rel), "utf-8");
|
|
27840
28162
|
if (a !== b) return false;
|
|
27841
28163
|
}
|
|
27842
28164
|
return true;
|
|
@@ -28017,7 +28339,7 @@ async function synthesizeLocally(opts) {
|
|
|
28017
28339
|
async function healStaleAnalysisConfig(globals) {
|
|
28018
28340
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
28019
28341
|
const standardPath = projectPath(STANDARD_FILE);
|
|
28020
|
-
if (!(0,
|
|
28342
|
+
if (!(0, import_node_fs56.existsSync)(configPath) || !(0, import_node_fs56.existsSync)(standardPath)) return;
|
|
28021
28343
|
const validation = validatePatternIds();
|
|
28022
28344
|
if (validation.status !== "invalid") return;
|
|
28023
28345
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
@@ -28114,17 +28436,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
28114
28436
|
async function installSkills(force, step) {
|
|
28115
28437
|
step("Installing skills");
|
|
28116
28438
|
const dataDir = resolveDataDir2();
|
|
28117
|
-
const skillsSource = (0,
|
|
28439
|
+
const skillsSource = (0, import_node_path40.join)(dataDir, "skills");
|
|
28118
28440
|
const skillsDest = ".claude/skills";
|
|
28119
28441
|
let skillsInstalled = 0;
|
|
28120
28442
|
for (const skill of SKILLS) {
|
|
28121
|
-
const src = (0,
|
|
28122
|
-
const dest = (0,
|
|
28123
|
-
if (!(0,
|
|
28443
|
+
const src = (0, import_node_path40.join)(skillsSource, skill);
|
|
28444
|
+
const dest = (0, import_node_path40.join)(skillsDest, skill);
|
|
28445
|
+
if (!(0, import_node_fs56.existsSync)(src)) {
|
|
28124
28446
|
printWarn(` Skill data not found: ${skill}`);
|
|
28125
28447
|
continue;
|
|
28126
28448
|
}
|
|
28127
|
-
if ((0,
|
|
28449
|
+
if ((0, import_node_fs56.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
28128
28450
|
skillsInstalled++;
|
|
28129
28451
|
continue;
|
|
28130
28452
|
}
|
|
@@ -28263,7 +28585,7 @@ function registerInitCommand(program2) {
|
|
|
28263
28585
|
const staleMarker = clearStalePluginMarker();
|
|
28264
28586
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
28265
28587
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
28266
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
28588
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs56.existsSync)(m));
|
|
28267
28589
|
if (!isProject) {
|
|
28268
28590
|
printError("No project detected in the current directory.");
|
|
28269
28591
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -28353,7 +28675,7 @@ function registerInitCommand(program2) {
|
|
|
28353
28675
|
printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
|
|
28354
28676
|
}
|
|
28355
28677
|
await scaffoldProject(step, defaultsOnly);
|
|
28356
|
-
const globalVerityDir = (0,
|
|
28678
|
+
const globalVerityDir = (0, import_node_path40.join)(process.env.HOME ?? "", ".verity");
|
|
28357
28679
|
await (0, import_promises19.mkdir)(globalVerityDir, { recursive: true });
|
|
28358
28680
|
console.log("");
|
|
28359
28681
|
step("Wiring Claude Code hooks");
|
|
@@ -28422,7 +28744,7 @@ function registerInitCommand(program2) {
|
|
|
28422
28744
|
}
|
|
28423
28745
|
step("Your project's Standard");
|
|
28424
28746
|
let haveStandard = false;
|
|
28425
|
-
if ((0,
|
|
28747
|
+
if ((0, import_node_fs56.existsSync)(projectPath(STANDARD_FILE))) {
|
|
28426
28748
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
28427
28749
|
haveStandard = true;
|
|
28428
28750
|
} else {
|
|
@@ -28452,7 +28774,7 @@ function registerInitCommand(program2) {
|
|
|
28452
28774
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
28453
28775
|
init: {
|
|
28454
28776
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28455
|
-
cli_version: true ? "0.33.
|
|
28777
|
+
cli_version: true ? "0.33.1-experimental.1378de3" : "dev"
|
|
28456
28778
|
}
|
|
28457
28779
|
});
|
|
28458
28780
|
} catch (err) {
|
|
@@ -28502,8 +28824,8 @@ function registerInitCommand(program2) {
|
|
|
28502
28824
|
}
|
|
28503
28825
|
|
|
28504
28826
|
// src/commands/uninstall.ts
|
|
28505
|
-
var
|
|
28506
|
-
var
|
|
28827
|
+
var import_node_fs57 = require("node:fs");
|
|
28828
|
+
var import_node_path41 = require("node:path");
|
|
28507
28829
|
function registerUninstallCommand(program2) {
|
|
28508
28830
|
program2.command("uninstall").description("Remove Verity from this project (skills, hooks, .verity/, VERITY.md)").option("--dry-run", "Show what would be removed without doing it").option("--purge-global", "Also remove ~/.verity/ (deletes saved tokens \u2014 reconnect requires re-registration)").option("--keep-verity-md", "Keep the project root VERITY.md file").action(async (opts) => {
|
|
28509
28831
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -28512,11 +28834,11 @@ function registerUninstallCommand(program2) {
|
|
|
28512
28834
|
const actions = [];
|
|
28513
28835
|
const skillsRoot = projectPath(".claude/skills");
|
|
28514
28836
|
for (const name of PROJECT_SKILL_NAMES) {
|
|
28515
|
-
const dir = (0,
|
|
28516
|
-
if ((0,
|
|
28837
|
+
const dir = (0, import_node_path41.join)(skillsRoot, name);
|
|
28838
|
+
if ((0, import_node_fs57.existsSync)(dir)) {
|
|
28517
28839
|
actions.push({
|
|
28518
28840
|
label: `Remove .claude/skills/${name}/`,
|
|
28519
|
-
apply: () => (0,
|
|
28841
|
+
apply: () => (0, import_node_fs57.rmSync)(dir, { recursive: true, force: true })
|
|
28520
28842
|
});
|
|
28521
28843
|
}
|
|
28522
28844
|
}
|
|
@@ -28530,24 +28852,24 @@ function registerUninstallCommand(program2) {
|
|
|
28530
28852
|
});
|
|
28531
28853
|
}
|
|
28532
28854
|
const verityDir = projectPath(VERITY_DIR);
|
|
28533
|
-
if ((0,
|
|
28855
|
+
if ((0, import_node_fs57.existsSync)(verityDir)) {
|
|
28534
28856
|
actions.push({
|
|
28535
28857
|
label: `Remove ${VERITY_DIR}/`,
|
|
28536
|
-
apply: () => (0,
|
|
28858
|
+
apply: () => (0, import_node_fs57.rmSync)(verityDir, { recursive: true, force: true })
|
|
28537
28859
|
});
|
|
28538
28860
|
}
|
|
28539
28861
|
if (!keepVerityMd) {
|
|
28540
28862
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
28541
|
-
if ((0,
|
|
28863
|
+
if ((0, import_node_fs57.existsSync)(verityMd)) {
|
|
28542
28864
|
actions.push({
|
|
28543
28865
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
28544
|
-
apply: () => (0,
|
|
28866
|
+
apply: () => (0, import_node_fs57.rmSync)(verityMd, { force: true })
|
|
28545
28867
|
});
|
|
28546
28868
|
}
|
|
28547
28869
|
}
|
|
28548
28870
|
const cleanupEmptyDir = (path) => {
|
|
28549
|
-
if ((0,
|
|
28550
|
-
(0,
|
|
28871
|
+
if ((0, import_node_fs57.existsSync)(path) && (0, import_node_fs57.statSync)(path).isDirectory() && (0, import_node_fs57.readdirSync)(path).length === 0) {
|
|
28872
|
+
(0, import_node_fs57.rmdirSync)(path);
|
|
28551
28873
|
}
|
|
28552
28874
|
};
|
|
28553
28875
|
actions.push({
|
|
@@ -28558,11 +28880,11 @@ function registerUninstallCommand(program2) {
|
|
|
28558
28880
|
}
|
|
28559
28881
|
});
|
|
28560
28882
|
const home = process.env.HOME ?? "";
|
|
28561
|
-
const globalVerityDir = (0,
|
|
28562
|
-
if (purgeGlobal && (0,
|
|
28883
|
+
const globalVerityDir = (0, import_node_path41.join)(home, ".verity");
|
|
28884
|
+
if (purgeGlobal && (0, import_node_fs57.existsSync)(globalVerityDir)) {
|
|
28563
28885
|
actions.push({
|
|
28564
28886
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
28565
|
-
apply: () => (0,
|
|
28887
|
+
apply: () => (0, import_node_fs57.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
28566
28888
|
});
|
|
28567
28889
|
}
|
|
28568
28890
|
if (actions.length === 0) {
|
|
@@ -28756,8 +29078,8 @@ function registerTaskCommands(program2) {
|
|
|
28756
29078
|
}
|
|
28757
29079
|
|
|
28758
29080
|
// src/commands/reset.ts
|
|
28759
|
-
var
|
|
28760
|
-
var
|
|
29081
|
+
var import_node_fs58 = require("node:fs");
|
|
29082
|
+
var import_node_path42 = require("node:path");
|
|
28761
29083
|
function registerResetCommand(program2) {
|
|
28762
29084
|
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) => {
|
|
28763
29085
|
const globals = program2.opts();
|
|
@@ -28794,11 +29116,11 @@ function registerResetCommand(program2) {
|
|
|
28794
29116
|
}
|
|
28795
29117
|
const cacheDir = projectPath(CACHE_DIR);
|
|
28796
29118
|
let purged = 0;
|
|
28797
|
-
if ((0,
|
|
28798
|
-
for (const entry of (0,
|
|
29119
|
+
if ((0, import_node_fs58.existsSync)(cacheDir)) {
|
|
29120
|
+
for (const entry of (0, import_node_fs58.readdirSync)(cacheDir)) {
|
|
28799
29121
|
if (entry.startsWith("pending-")) {
|
|
28800
29122
|
try {
|
|
28801
|
-
(0,
|
|
29123
|
+
(0, import_node_fs58.unlinkSync)((0, import_node_path42.join)(cacheDir, entry));
|
|
28802
29124
|
purged++;
|
|
28803
29125
|
} catch {
|
|
28804
29126
|
}
|
|
@@ -28813,19 +29135,19 @@ function registerResetCommand(program2) {
|
|
|
28813
29135
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
28814
29136
|
];
|
|
28815
29137
|
for (const file of filesToClear) {
|
|
28816
|
-
if ((0,
|
|
29138
|
+
if ((0, import_node_fs58.existsSync)(file)) {
|
|
28817
29139
|
try {
|
|
28818
|
-
(0,
|
|
29140
|
+
(0, import_node_fs58.writeFileSync)(file, "");
|
|
28819
29141
|
} catch {
|
|
28820
29142
|
}
|
|
28821
29143
|
}
|
|
28822
29144
|
}
|
|
28823
29145
|
if (opts.all) {
|
|
28824
29146
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
28825
|
-
if ((0,
|
|
28826
|
-
for (const entry of (0,
|
|
29147
|
+
if ((0, import_node_fs58.existsSync)(logsDir)) {
|
|
29148
|
+
for (const entry of (0, import_node_fs58.readdirSync)(logsDir)) {
|
|
28827
29149
|
try {
|
|
28828
|
-
(0,
|
|
29150
|
+
(0, import_node_fs58.unlinkSync)((0, import_node_path42.join)(logsDir, entry));
|
|
28829
29151
|
} catch {
|
|
28830
29152
|
}
|
|
28831
29153
|
}
|
|
@@ -28837,7 +29159,7 @@ function registerResetCommand(program2) {
|
|
|
28837
29159
|
}
|
|
28838
29160
|
|
|
28839
29161
|
// src/commands/reflect.ts
|
|
28840
|
-
var
|
|
29162
|
+
var import_node_fs59 = require("node:fs");
|
|
28841
29163
|
|
|
28842
29164
|
// src/lib/reflection-globs.ts
|
|
28843
29165
|
var MAX_GLOBS = 6;
|
|
@@ -28875,7 +29197,7 @@ async function writeNodeToDisk(args) {
|
|
|
28875
29197
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
28876
29198
|
);
|
|
28877
29199
|
if (written === 0) return false;
|
|
28878
|
-
return (0,
|
|
29200
|
+
return (0, import_node_fs59.existsSync)(projectPath(`${VERITY_DIR}/memory/${args.filePath}`));
|
|
28879
29201
|
} catch {
|
|
28880
29202
|
return false;
|
|
28881
29203
|
}
|
|
@@ -28954,7 +29276,7 @@ function registerReflectCommand(program2) {
|
|
|
28954
29276
|
const fileGlobs = explicitGlobs.length > 0 ? explicitGlobs : derivedGlobs.length > 0 ? derivedGlobs : inheritedGlobs;
|
|
28955
29277
|
const result = await apiRequest({
|
|
28956
29278
|
method: "POST",
|
|
28957
|
-
path: "/compound/
|
|
29279
|
+
path: "/compound/reflect",
|
|
28958
29280
|
serviceUrl,
|
|
28959
29281
|
token,
|
|
28960
29282
|
body: {
|
|
@@ -28987,6 +29309,8 @@ function registerReflectCommand(program2) {
|
|
|
28987
29309
|
const nodeId = result.data.node_id;
|
|
28988
29310
|
const filePath = result.data.file_path;
|
|
28989
29311
|
const viewUrl = typeof result.data.view_url === "string" ? result.data.view_url : null;
|
|
29312
|
+
const recordedSource = typeof result.data.source === "string" ? result.data.source : source;
|
|
29313
|
+
const recordedAsUser = recordedSource === "user";
|
|
28990
29314
|
const content = typeof result.data.content === "string" ? result.data.content : null;
|
|
28991
29315
|
const synced = content !== null && await writeNodeToDisk({ filePath, content, nodeId });
|
|
28992
29316
|
printInfo(
|
|
@@ -28994,8 +29318,13 @@ function registerReflectCommand(program2) {
|
|
|
28994
29318
|
);
|
|
28995
29319
|
if (viewUrl) printInfo(` ${viewUrl}`);
|
|
28996
29320
|
printInfo(
|
|
28997
|
-
|
|
29321
|
+
recordedAsUser ? " Recorded as yours (source: user)." : " Auto-recorded from this task \u2014 nobody reviewed it. Edit or delete the file if it is wrong."
|
|
28998
29322
|
);
|
|
29323
|
+
if (recordedSource !== source) {
|
|
29324
|
+
printWarn(
|
|
29325
|
+
`Provenance mismatch: sent source "${source}", the service recorded "${recordedSource}". Correct ${nodeId} on the dashboard \u2014 a draft stored as human-authored cannot be told apart later.`
|
|
29326
|
+
);
|
|
29327
|
+
}
|
|
28999
29328
|
if (fileGlobs.length === 0) {
|
|
29000
29329
|
printWarn(
|
|
29001
29330
|
'No files matched \u2014 this reflection will not surface in future reviews. Cite a path in the text, or pass --file-globs "<path or glob>".'
|
|
@@ -29367,8 +29696,8 @@ function registerTelemetryCommands(program2) {
|
|
|
29367
29696
|
}
|
|
29368
29697
|
|
|
29369
29698
|
// src/cli.ts
|
|
29370
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.33.
|
|
29371
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.
|
|
29699
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.33.1-experimental.1378de3").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) => {
|
|
29700
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.1-experimental.1378de3");
|
|
29372
29701
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
29373
29702
|
try {
|
|
29374
29703
|
await foldLegacyLocalCredential();
|