@codacy/verity-cli 0.33.0-experimental.d60f544 → 0.33.0
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 +16 -0
- package/bin/verity.js +852 -668
- 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;
|
|
@@ -10523,7 +10524,7 @@ var SECURITY_PATTERNS = [
|
|
|
10523
10524
|
/Dockerfile/
|
|
10524
10525
|
];
|
|
10525
10526
|
var PROD_SERVICE_URL = "https://ofcamwrjwrkazqvdchko.supabase.co/functions/v1";
|
|
10526
|
-
var DEFAULT_SERVICE_URL = "
|
|
10527
|
+
var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
|
|
10527
10528
|
var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
|
|
10528
10529
|
var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
|
|
10529
10530
|
var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
@@ -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,8 +12907,8 @@ 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;
|
|
12875
12914
|
return {
|
|
@@ -12886,23 +12925,23 @@ function recordPluginOwnership(sessionId) {
|
|
|
12886
12925
|
const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
|
|
12887
12926
|
if (!pluginRoot) return;
|
|
12888
12927
|
try {
|
|
12889
|
-
(0,
|
|
12928
|
+
(0, import_node_fs7.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
12890
12929
|
const marker = {
|
|
12891
12930
|
session_id: sessionId,
|
|
12892
12931
|
plugin_root: pluginRoot,
|
|
12893
12932
|
version: process.env.VERITY_PLUGIN_VERSION || null,
|
|
12894
12933
|
ts: Math.floor(Date.now() / 1e3)
|
|
12895
12934
|
};
|
|
12896
|
-
(0,
|
|
12935
|
+
(0, import_node_fs7.writeFileSync)(markerPath(), JSON.stringify(marker));
|
|
12897
12936
|
} catch {
|
|
12898
12937
|
}
|
|
12899
12938
|
}
|
|
12900
12939
|
function claudeConfigDir() {
|
|
12901
|
-
return process.env.CLAUDE_CONFIG_DIR || (0,
|
|
12940
|
+
return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path8.join)((0, import_node_os2.homedir)(), ".claude");
|
|
12902
12941
|
}
|
|
12903
12942
|
function readJsonFile(path) {
|
|
12904
12943
|
try {
|
|
12905
|
-
const parsed = JSON.parse((0,
|
|
12944
|
+
const parsed = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf-8"));
|
|
12906
12945
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
12907
12946
|
} catch {
|
|
12908
12947
|
return null;
|
|
@@ -12910,9 +12949,9 @@ function readJsonFile(path) {
|
|
|
12910
12949
|
}
|
|
12911
12950
|
function enabledPluginSetting(key) {
|
|
12912
12951
|
const files = [
|
|
12913
|
-
projectPath((0,
|
|
12914
|
-
projectPath((0,
|
|
12915
|
-
(0,
|
|
12952
|
+
projectPath((0, import_node_path8.join)(".claude", "settings.local.json")),
|
|
12953
|
+
projectPath((0, import_node_path8.join)(".claude", "settings.json")),
|
|
12954
|
+
(0, import_node_path8.join)(claudeConfigDir(), "settings.json")
|
|
12916
12955
|
];
|
|
12917
12956
|
for (const file of files) {
|
|
12918
12957
|
const map = readJsonFile(file)?.enabledPlugins;
|
|
@@ -12924,27 +12963,16 @@ function enabledPluginSetting(key) {
|
|
|
12924
12963
|
}
|
|
12925
12964
|
function marketplaceLocations() {
|
|
12926
12965
|
const out = /* @__PURE__ */ new Map();
|
|
12927
|
-
const known = readJsonFile((0,
|
|
12966
|
+
const known = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
12928
12967
|
if (!known) return out;
|
|
12929
12968
|
for (const [name, entry] of Object.entries(known)) {
|
|
12930
12969
|
const loc2 = entry?.installLocation;
|
|
12931
|
-
if (typeof loc2 === "string" && loc2) out.set(name, (0,
|
|
12970
|
+
if (typeof loc2 === "string" && loc2) out.set(name, (0, import_node_path8.resolve)(loc2));
|
|
12932
12971
|
}
|
|
12933
12972
|
return out;
|
|
12934
12973
|
}
|
|
12935
12974
|
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;
|
|
12975
|
+
return whichSync("verity", { real: false });
|
|
12948
12976
|
}
|
|
12949
12977
|
function verityOnPath() {
|
|
12950
12978
|
return verityPathEntry() !== null;
|
|
@@ -12953,7 +12981,7 @@ function globalVerityVersion() {
|
|
|
12953
12981
|
const entry = verityPathEntry();
|
|
12954
12982
|
if (!entry) return null;
|
|
12955
12983
|
try {
|
|
12956
|
-
const pkg = readJsonFile((0,
|
|
12984
|
+
const pkg = readJsonFile((0, import_node_path8.join)((0, import_node_path8.dirname)((0, import_node_fs7.realpathSync)(entry)), "..", "package.json"));
|
|
12957
12985
|
if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
|
|
12958
12986
|
return pkg.version;
|
|
12959
12987
|
} catch {
|
|
@@ -12965,7 +12993,7 @@ function pluginCliInvocation() {
|
|
|
12965
12993
|
if (!root) return null;
|
|
12966
12994
|
const onPath = globalVerityVersion();
|
|
12967
12995
|
if (onPath !== null && onPath === activePluginVersion()) return null;
|
|
12968
|
-
return `node ${JSON.stringify((0,
|
|
12996
|
+
return `node ${JSON.stringify((0, import_node_path8.join)(root, "scripts", "verity.mjs"))}`;
|
|
12969
12997
|
}
|
|
12970
12998
|
function cliVersionSkew() {
|
|
12971
12999
|
if (!process.env.VERITY_PLUGIN_ROOT) return null;
|
|
@@ -12984,7 +13012,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
|
|
|
12984
13012
|
function marketplaceConflict() {
|
|
12985
13013
|
const wanted = VERITY_MARKETPLACE;
|
|
12986
13014
|
for (const file of ["settings.json", "settings.local.json"]) {
|
|
12987
|
-
const path = (0,
|
|
13015
|
+
const path = (0, import_node_path8.join)(claudeConfigDir(), file);
|
|
12988
13016
|
const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
|
|
12989
13017
|
const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
|
|
12990
13018
|
if (entry2 && typeof entry2 === "object") {
|
|
@@ -12994,7 +13022,7 @@ function marketplaceConflict() {
|
|
|
12994
13022
|
}
|
|
12995
13023
|
}
|
|
12996
13024
|
}
|
|
12997
|
-
const known = readJsonFile((0,
|
|
13025
|
+
const known = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
12998
13026
|
const entry = known?.[wanted];
|
|
12999
13027
|
if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
|
|
13000
13028
|
return { name: wanted, declaredAs: describeSource(entry.source) };
|
|
@@ -13015,7 +13043,7 @@ function describeSource(src) {
|
|
|
13015
13043
|
return target ? `${kind} \u2192 ${target}` : kind;
|
|
13016
13044
|
}
|
|
13017
13045
|
function legacyMarketplaceInstall() {
|
|
13018
|
-
const plugins = readJsonFile((0,
|
|
13046
|
+
const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
13019
13047
|
if (!plugins || typeof plugins !== "object") return null;
|
|
13020
13048
|
for (const key of Object.keys(plugins)) {
|
|
13021
13049
|
const at = key.lastIndexOf("@");
|
|
@@ -13027,13 +13055,13 @@ function legacyMarketplaceInstall() {
|
|
|
13027
13055
|
}
|
|
13028
13056
|
function realpathOr(p) {
|
|
13029
13057
|
try {
|
|
13030
|
-
return
|
|
13058
|
+
return import_node_fs7.realpathSync.native(p);
|
|
13031
13059
|
} catch {
|
|
13032
|
-
return (0,
|
|
13060
|
+
return (0, import_node_path8.resolve)(p);
|
|
13033
13061
|
}
|
|
13034
13062
|
}
|
|
13035
13063
|
function isWithin(want, dir) {
|
|
13036
|
-
return want === dir || want.startsWith(dir +
|
|
13064
|
+
return want === dir || want.startsWith(dir + import_node_path8.sep);
|
|
13037
13065
|
}
|
|
13038
13066
|
function entryAppliesHere(entry, here) {
|
|
13039
13067
|
const e = entry;
|
|
@@ -13043,9 +13071,9 @@ function entryAppliesHere(entry, here) {
|
|
|
13043
13071
|
return forProject === here;
|
|
13044
13072
|
}
|
|
13045
13073
|
function registrySays(pluginRoot) {
|
|
13046
|
-
const plugins = readJsonFile((0,
|
|
13074
|
+
const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
13047
13075
|
if (!plugins || typeof plugins !== "object") return "unverified";
|
|
13048
|
-
const want = (0,
|
|
13076
|
+
const want = (0, import_node_path8.resolve)(pluginRoot);
|
|
13049
13077
|
const here = realpathOr(repoRoot());
|
|
13050
13078
|
const markets = marketplaceLocations();
|
|
13051
13079
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -13054,15 +13082,15 @@ function registrySays(pluginRoot) {
|
|
|
13054
13082
|
const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
|
|
13055
13083
|
const claims = applicable.some((entry) => {
|
|
13056
13084
|
const installPath = entry?.installPath;
|
|
13057
|
-
return typeof installPath === "string" && (0,
|
|
13085
|
+
return typeof installPath === "string" && (0, import_node_path8.resolve)(installPath) === want;
|
|
13058
13086
|
}) || source !== void 0 && applicable.length > 0 && isWithin(want, source);
|
|
13059
13087
|
if (claims) {
|
|
13060
13088
|
if (enabledPluginSetting(key) === false) return "gone";
|
|
13061
|
-
return (0,
|
|
13089
|
+
return (0, import_node_fs7.existsSync)(pluginRoot) ? "live" : "gone";
|
|
13062
13090
|
}
|
|
13063
13091
|
}
|
|
13064
|
-
const managed = (0,
|
|
13065
|
-
return want === managed || want.startsWith(managed +
|
|
13092
|
+
const managed = (0, import_node_path8.resolve)((0, import_node_path8.join)(claudeConfigDir(), "plugins", "cache"));
|
|
13093
|
+
return want === managed || want.startsWith(managed + import_node_path8.sep) ? "gone" : "unverified";
|
|
13066
13094
|
}
|
|
13067
13095
|
var _live = /* @__PURE__ */ new Map();
|
|
13068
13096
|
function pluginLiveness(pluginRoot) {
|
|
@@ -13076,7 +13104,7 @@ function clearStalePluginMarker() {
|
|
|
13076
13104
|
const marker = readMarker();
|
|
13077
13105
|
if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
|
|
13078
13106
|
try {
|
|
13079
|
-
(0,
|
|
13107
|
+
(0, import_node_fs7.rmSync)(markerPath(), { force: true });
|
|
13080
13108
|
} catch {
|
|
13081
13109
|
return null;
|
|
13082
13110
|
}
|
|
@@ -13104,7 +13132,7 @@ function pluginActiveHere() {
|
|
|
13104
13132
|
return activePluginInstall() !== null;
|
|
13105
13133
|
}
|
|
13106
13134
|
function registeredVerityPlugin() {
|
|
13107
|
-
const plugins = readJsonFile((0,
|
|
13135
|
+
const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
13108
13136
|
if (!plugins || typeof plugins !== "object") return null;
|
|
13109
13137
|
const here = realpathOr(repoRoot());
|
|
13110
13138
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -13114,7 +13142,7 @@ function registeredVerityPlugin() {
|
|
|
13114
13142
|
for (const entry of Array.isArray(value) ? value : []) {
|
|
13115
13143
|
const e = entry;
|
|
13116
13144
|
const installPath = typeof e.installPath === "string" ? e.installPath : "";
|
|
13117
|
-
if (!installPath || !(0,
|
|
13145
|
+
if (!installPath || !(0, import_node_fs7.existsSync)(installPath)) continue;
|
|
13118
13146
|
if (!entryAppliesHere(entry, here)) continue;
|
|
13119
13147
|
return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
|
|
13120
13148
|
}
|
|
@@ -13299,7 +13327,7 @@ var import_node_crypto8 = require("node:crypto");
|
|
|
13299
13327
|
|
|
13300
13328
|
// src/lib/conversation-buffer.ts
|
|
13301
13329
|
var import_promises5 = require("node:fs/promises");
|
|
13302
|
-
var
|
|
13330
|
+
var import_node_fs8 = require("node:fs");
|
|
13303
13331
|
var import_node_child_process5 = require("node:child_process");
|
|
13304
13332
|
var import_node_crypto = require("node:crypto");
|
|
13305
13333
|
function stripImageReferences(text) {
|
|
@@ -13335,7 +13363,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
|
|
|
13335
13363
|
}
|
|
13336
13364
|
async function readAndClearConversationBuffer(currentSessionId) {
|
|
13337
13365
|
try {
|
|
13338
|
-
if ((0,
|
|
13366
|
+
if ((0, import_node_fs8.existsSync)(CONVERSATION_BUFFER_FILE)) {
|
|
13339
13367
|
const entries = await readBufferEntries();
|
|
13340
13368
|
let mine = entries;
|
|
13341
13369
|
let others = [];
|
|
@@ -13359,7 +13387,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
|
|
|
13359
13387
|
};
|
|
13360
13388
|
}
|
|
13361
13389
|
}
|
|
13362
|
-
if ((0,
|
|
13390
|
+
if ((0, import_node_fs8.existsSync)(INTENT_FILE)) {
|
|
13363
13391
|
try {
|
|
13364
13392
|
const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
|
|
13365
13393
|
await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
|
|
@@ -13652,9 +13680,9 @@ function isCommandOnlyTurn(input) {
|
|
|
13652
13680
|
|
|
13653
13681
|
// src/lib/context-identity.ts
|
|
13654
13682
|
var import_node_crypto2 = require("node:crypto");
|
|
13655
|
-
var
|
|
13683
|
+
var import_node_fs9 = require("node:fs");
|
|
13656
13684
|
var import_node_os3 = require("node:os");
|
|
13657
|
-
var
|
|
13685
|
+
var import_node_path9 = require("node:path");
|
|
13658
13686
|
var SHARED_SENTINELS = /* @__PURE__ */ new Set([
|
|
13659
13687
|
"",
|
|
13660
13688
|
"-",
|
|
@@ -13692,7 +13720,7 @@ function contextIdentity(input) {
|
|
|
13692
13720
|
if (rawTree && !isSharedSentinel(rawTree)) {
|
|
13693
13721
|
let resolved = rawTree;
|
|
13694
13722
|
try {
|
|
13695
|
-
resolved =
|
|
13723
|
+
resolved = import_node_fs9.realpathSync.native(rawTree);
|
|
13696
13724
|
} catch {
|
|
13697
13725
|
}
|
|
13698
13726
|
treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
@@ -13708,13 +13736,13 @@ function contextIdentity(input) {
|
|
|
13708
13736
|
}
|
|
13709
13737
|
function verityHome() {
|
|
13710
13738
|
const override = process.env.VERITY_HOME;
|
|
13711
|
-
return override && override.trim() ? (0,
|
|
13739
|
+
return override && override.trim() ? (0, import_node_path9.resolve)(override) : (0, import_node_path9.join)((0, import_node_os3.homedir)(), ".verity");
|
|
13712
13740
|
}
|
|
13713
13741
|
function dossierDir(identity) {
|
|
13714
|
-
return (0,
|
|
13742
|
+
return (0, import_node_path9.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
|
|
13715
13743
|
}
|
|
13716
13744
|
function treeDir(identity) {
|
|
13717
|
-
return (0,
|
|
13745
|
+
return (0, import_node_path9.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
|
|
13718
13746
|
}
|
|
13719
13747
|
function scopeIdentity(token, sessionId) {
|
|
13720
13748
|
const t = (token ?? "").trim();
|
|
@@ -13729,8 +13757,8 @@ function sessionScopeKey(token, sessionId) {
|
|
|
13729
13757
|
|
|
13730
13758
|
// src/lib/task-context-buffer.ts
|
|
13731
13759
|
var import_promises6 = require("node:fs/promises");
|
|
13732
|
-
var
|
|
13733
|
-
var
|
|
13760
|
+
var import_node_fs10 = require("node:fs");
|
|
13761
|
+
var import_node_path10 = require("node:path");
|
|
13734
13762
|
var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
|
|
13735
13763
|
var MAX_BUFFER_BYTES = 500 * 1024;
|
|
13736
13764
|
var MAX_PROMPT_CHARS = 2e3;
|
|
@@ -13769,7 +13797,7 @@ async function appendResponseToTaskBuffer(taskId, assistantResponse, actionSumma
|
|
|
13769
13797
|
}
|
|
13770
13798
|
async function readTaskContextBuffer(taskId) {
|
|
13771
13799
|
const filePath = bufferPath(taskId);
|
|
13772
|
-
if (!(0,
|
|
13800
|
+
if (!(0, import_node_fs10.existsSync)(filePath)) return null;
|
|
13773
13801
|
try {
|
|
13774
13802
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
13775
13803
|
if (!content.trim()) return null;
|
|
@@ -13803,12 +13831,12 @@ async function readTaskContextBuffer(taskId) {
|
|
|
13803
13831
|
}
|
|
13804
13832
|
async function cleanupTaskContextBuffers() {
|
|
13805
13833
|
try {
|
|
13806
|
-
if (!(0,
|
|
13834
|
+
if (!(0, import_node_fs10.existsSync)(TASK_CONTEXT_DIR)) return;
|
|
13807
13835
|
const files = await (0, import_promises6.readdir)(TASK_CONTEXT_DIR);
|
|
13808
13836
|
const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
13809
13837
|
for (const file of files) {
|
|
13810
13838
|
if (!file.endsWith(".jsonl")) continue;
|
|
13811
|
-
const filePath = (0,
|
|
13839
|
+
const filePath = (0, import_node_path10.join)(TASK_CONTEXT_DIR, file);
|
|
13812
13840
|
try {
|
|
13813
13841
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
13814
13842
|
if (stats.mtimeMs < cutoffMs) {
|
|
@@ -13822,13 +13850,13 @@ async function cleanupTaskContextBuffers() {
|
|
|
13822
13850
|
}
|
|
13823
13851
|
function bufferPath(taskId) {
|
|
13824
13852
|
const safe = taskId.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
13825
|
-
return (0,
|
|
13853
|
+
return (0, import_node_path10.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
|
|
13826
13854
|
}
|
|
13827
13855
|
async function appendEntry(taskId, entry) {
|
|
13828
13856
|
try {
|
|
13829
13857
|
await (0, import_promises6.mkdir)(TASK_CONTEXT_DIR, { recursive: true });
|
|
13830
13858
|
const filePath = bufferPath(taskId);
|
|
13831
|
-
if ((0,
|
|
13859
|
+
if ((0, import_node_fs10.existsSync)(filePath)) {
|
|
13832
13860
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
13833
13861
|
if (stats.size >= MAX_BUFFER_BYTES) {
|
|
13834
13862
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
@@ -13839,7 +13867,7 @@ async function appendEntry(taskId, entry) {
|
|
|
13839
13867
|
}
|
|
13840
13868
|
}
|
|
13841
13869
|
const line = JSON.stringify(entry) + "\n";
|
|
13842
|
-
const existing = (0,
|
|
13870
|
+
const existing = (0, import_node_fs10.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
|
|
13843
13871
|
await (0, import_promises6.writeFile)(filePath, existing + line);
|
|
13844
13872
|
} catch {
|
|
13845
13873
|
}
|
|
@@ -13847,20 +13875,20 @@ async function appendEntry(taskId, entry) {
|
|
|
13847
13875
|
|
|
13848
13876
|
// src/lib/memory-retrieval.ts
|
|
13849
13877
|
var import_promises8 = require("node:fs/promises");
|
|
13850
|
-
var
|
|
13851
|
-
var
|
|
13878
|
+
var import_node_fs12 = require("node:fs");
|
|
13879
|
+
var import_node_path12 = require("node:path");
|
|
13852
13880
|
|
|
13853
13881
|
// src/lib/org-mirror.ts
|
|
13854
|
-
var
|
|
13882
|
+
var import_node_fs11 = require("node:fs");
|
|
13855
13883
|
var import_promises7 = require("node:fs/promises");
|
|
13856
|
-
var
|
|
13884
|
+
var import_node_path11 = require("node:path");
|
|
13857
13885
|
var ORG_KINDS = ["decision", "security", "gotcha", "pattern", "domain", "integration"];
|
|
13858
13886
|
var STATE_FILE = ".org-pull-state.json";
|
|
13859
13887
|
var BODY_MAX = 8192;
|
|
13860
13888
|
function orgMirrorDir(remote = requestRemote()) {
|
|
13861
13889
|
const parsed = parseRemote(remote);
|
|
13862
13890
|
if (!parsed) return null;
|
|
13863
|
-
return (0,
|
|
13891
|
+
return (0, import_node_path11.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
|
|
13864
13892
|
}
|
|
13865
13893
|
function slugify(s) {
|
|
13866
13894
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
@@ -13926,7 +13954,7 @@ function parseOrgNode(content) {
|
|
|
13926
13954
|
}
|
|
13927
13955
|
async function readState(dir) {
|
|
13928
13956
|
try {
|
|
13929
|
-
const parsed = JSON.parse(await (0, import_promises7.readFile)((0,
|
|
13957
|
+
const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path11.join)(dir, STATE_FILE), "utf-8"));
|
|
13930
13958
|
return {
|
|
13931
13959
|
version: typeof parsed?.version === "string" ? parsed.version : null,
|
|
13932
13960
|
organization: parsed?.organization && typeof parsed.organization.id === "string" ? parsed.organization : null,
|
|
@@ -13938,7 +13966,7 @@ async function readState(dir) {
|
|
|
13938
13966
|
}
|
|
13939
13967
|
async function writeState(dir, state) {
|
|
13940
13968
|
await (0, import_promises7.mkdir)(dir, { recursive: true });
|
|
13941
|
-
await (0, import_promises7.writeFile)((0,
|
|
13969
|
+
await (0, import_promises7.writeFile)((0, import_node_path11.join)(dir, STATE_FILE), JSON.stringify({
|
|
13942
13970
|
...state.version ? { version: state.version } : {},
|
|
13943
13971
|
organization: state.organization,
|
|
13944
13972
|
pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -14003,24 +14031,24 @@ async function pullOrgKnowledge(opts) {
|
|
|
14003
14031
|
for (const n of nodes) {
|
|
14004
14032
|
const rel = orgNodePath(n);
|
|
14005
14033
|
if (written.has(rel)) continue;
|
|
14006
|
-
await (0, import_promises7.mkdir)((0,
|
|
14007
|
-
await (0, import_promises7.writeFile)((0,
|
|
14034
|
+
await (0, import_promises7.mkdir)((0, import_node_path11.join)(dir, rel.split("/")[0]), { recursive: true });
|
|
14035
|
+
await (0, import_promises7.writeFile)((0, import_node_path11.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
|
|
14008
14036
|
written.add(rel);
|
|
14009
14037
|
}
|
|
14010
14038
|
for (const rel of state.files) {
|
|
14011
|
-
if (!written.has(rel)) await (0, import_promises7.rm)((0,
|
|
14039
|
+
if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path11.join)(dir, rel), { force: true });
|
|
14012
14040
|
}
|
|
14013
|
-
await (0, import_promises7.writeFile)((0,
|
|
14041
|
+
await (0, import_promises7.writeFile)((0, import_node_path11.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
|
|
14014
14042
|
await writeState(dir, { version: org ? page.version : null, organization: org, files: [...written].sort() });
|
|
14015
14043
|
return { ok: true, status: org ? "pulled" : "none", received: nodes.length, dir };
|
|
14016
14044
|
}
|
|
14017
14045
|
async function readOrgMirror(remote = requestRemote()) {
|
|
14018
14046
|
const dir = orgMirrorDir(remote);
|
|
14019
|
-
if (!dir || !(0,
|
|
14047
|
+
if (!dir || !(0, import_node_fs11.existsSync)(dir)) return [];
|
|
14020
14048
|
const out = [];
|
|
14021
14049
|
for (const kind of ORG_KINDS) {
|
|
14022
|
-
const kindDir = (0,
|
|
14023
|
-
if (!(0,
|
|
14050
|
+
const kindDir = (0, import_node_path11.join)(dir, kind);
|
|
14051
|
+
if (!(0, import_node_fs11.existsSync)(kindDir)) continue;
|
|
14024
14052
|
let files;
|
|
14025
14053
|
try {
|
|
14026
14054
|
files = await (0, import_promises7.readdir)(kindDir);
|
|
@@ -14030,7 +14058,7 @@ async function readOrgMirror(remote = requestRemote()) {
|
|
|
14030
14058
|
for (const file of files) {
|
|
14031
14059
|
if (!file.endsWith(".md")) continue;
|
|
14032
14060
|
try {
|
|
14033
|
-
const node = parseOrgNode(await (0, import_promises7.readFile)((0,
|
|
14061
|
+
const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path11.join)(kindDir, file), "utf-8"));
|
|
14034
14062
|
if (node) out.push(node);
|
|
14035
14063
|
} catch {
|
|
14036
14064
|
}
|
|
@@ -14153,19 +14181,19 @@ function parseFrontmatter(content) {
|
|
|
14153
14181
|
return { fm, body: match[2].trim() };
|
|
14154
14182
|
}
|
|
14155
14183
|
async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
|
|
14156
|
-
const hasRepoGraph = (0,
|
|
14184
|
+
const hasRepoGraph = (0, import_node_fs12.existsSync)(memoryDir());
|
|
14157
14185
|
const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
|
|
14158
14186
|
const promptTokens = tokenize(promptText);
|
|
14159
14187
|
const nodes = [];
|
|
14160
14188
|
for (const domain of hasRepoGraph ? DOMAINS : []) {
|
|
14161
|
-
const domainDir = (0,
|
|
14162
|
-
if (!(0,
|
|
14189
|
+
const domainDir = (0, import_node_path12.join)(memoryDir(), domain);
|
|
14190
|
+
if (!(0, import_node_fs12.existsSync)(domainDir)) continue;
|
|
14163
14191
|
try {
|
|
14164
14192
|
const files = await (0, import_promises8.readdir)(domainDir);
|
|
14165
14193
|
for (const file of files) {
|
|
14166
14194
|
if (!file.endsWith(".md")) continue;
|
|
14167
14195
|
try {
|
|
14168
|
-
const content = await (0, import_promises8.readFile)((0,
|
|
14196
|
+
const content = await (0, import_promises8.readFile)((0, import_node_path12.join)(domainDir, file), "utf-8");
|
|
14169
14197
|
const { fm, body } = parseFrontmatter(content);
|
|
14170
14198
|
if (fm.status && fm.status !== "active") continue;
|
|
14171
14199
|
nodes.push({
|
|
@@ -14232,13 +14260,13 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
14232
14260
|
|
|
14233
14261
|
// src/lib/memory-sync.ts
|
|
14234
14262
|
var import_promises9 = require("node:fs/promises");
|
|
14235
|
-
var
|
|
14236
|
-
var
|
|
14263
|
+
var import_node_fs15 = require("node:fs");
|
|
14264
|
+
var import_node_path14 = require("node:path");
|
|
14237
14265
|
var import_node_crypto3 = require("node:crypto");
|
|
14238
14266
|
|
|
14239
14267
|
// src/lib/gitignore.ts
|
|
14240
14268
|
var import_node_child_process6 = require("node:child_process");
|
|
14241
|
-
var
|
|
14269
|
+
var import_node_fs13 = require("node:fs");
|
|
14242
14270
|
var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
|
|
14243
14271
|
var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
|
|
14244
14272
|
var VERITY_GITIGNORE_BLOCK = [
|
|
@@ -14322,7 +14350,7 @@ function fenceMemoryLines(lines) {
|
|
|
14322
14350
|
function ensureVerityGitignore() {
|
|
14323
14351
|
let content = "";
|
|
14324
14352
|
try {
|
|
14325
|
-
content = (0,
|
|
14353
|
+
content = (0, import_node_fs13.readFileSync)(".gitignore", "utf-8");
|
|
14326
14354
|
} catch {
|
|
14327
14355
|
}
|
|
14328
14356
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -14349,7 +14377,7 @@ function ensureVerityGitignore() {
|
|
|
14349
14377
|
const sep4 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
14350
14378
|
text = text + sep4 + VERITY_GITIGNORE_BLOCK;
|
|
14351
14379
|
}
|
|
14352
|
-
if (text !== content) (0,
|
|
14380
|
+
if (text !== content) (0, import_node_fs13.writeFileSync)(".gitignore", text);
|
|
14353
14381
|
return verified(
|
|
14354
14382
|
memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
|
|
14355
14383
|
);
|
|
@@ -14369,7 +14397,7 @@ function untrackMemory() {
|
|
|
14369
14397
|
function writeFencedBlock() {
|
|
14370
14398
|
let content = "";
|
|
14371
14399
|
try {
|
|
14372
|
-
content = (0,
|
|
14400
|
+
content = (0, import_node_fs13.readFileSync)(".gitignore", "utf-8");
|
|
14373
14401
|
} catch {
|
|
14374
14402
|
}
|
|
14375
14403
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -14381,7 +14409,7 @@ function writeFencedBlock() {
|
|
|
14381
14409
|
text = text + sep4 + VERITY_GITIGNORE_BLOCK;
|
|
14382
14410
|
}
|
|
14383
14411
|
try {
|
|
14384
|
-
(0,
|
|
14412
|
+
(0, import_node_fs13.writeFileSync)(".gitignore", text);
|
|
14385
14413
|
return true;
|
|
14386
14414
|
} catch {
|
|
14387
14415
|
return false;
|
|
@@ -14390,14 +14418,14 @@ function writeFencedBlock() {
|
|
|
14390
14418
|
function fenceMemory() {
|
|
14391
14419
|
let original = null;
|
|
14392
14420
|
try {
|
|
14393
|
-
original = (0,
|
|
14421
|
+
original = (0, import_node_fs13.readFileSync)(".gitignore", "utf-8");
|
|
14394
14422
|
} catch {
|
|
14395
14423
|
original = null;
|
|
14396
14424
|
}
|
|
14397
14425
|
const restore = () => {
|
|
14398
14426
|
try {
|
|
14399
|
-
if (original === null) (0,
|
|
14400
|
-
else (0,
|
|
14427
|
+
if (original === null) (0, import_node_fs13.rmSync)(".gitignore", { force: true });
|
|
14428
|
+
else (0, import_node_fs13.writeFileSync)(".gitignore", original);
|
|
14401
14429
|
} catch {
|
|
14402
14430
|
}
|
|
14403
14431
|
};
|
|
@@ -14415,7 +14443,7 @@ function fenceMemory() {
|
|
|
14415
14443
|
}
|
|
14416
14444
|
function memoryOptOut() {
|
|
14417
14445
|
try {
|
|
14418
|
-
return (0,
|
|
14446
|
+
return (0, import_node_fs13.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
|
|
14419
14447
|
} catch {
|
|
14420
14448
|
return false;
|
|
14421
14449
|
}
|
|
@@ -14423,13 +14451,13 @@ function memoryOptOut() {
|
|
|
14423
14451
|
function keepMemoryTracked() {
|
|
14424
14452
|
let content = "";
|
|
14425
14453
|
try {
|
|
14426
|
-
content = (0,
|
|
14454
|
+
content = (0, import_node_fs13.readFileSync)(".gitignore", "utf-8");
|
|
14427
14455
|
} catch {
|
|
14428
14456
|
}
|
|
14429
14457
|
if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
|
|
14430
14458
|
try {
|
|
14431
14459
|
const sep4 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
|
|
14432
|
-
(0,
|
|
14460
|
+
(0, import_node_fs13.writeFileSync)(".gitignore", content + sep4 + MEMORY_OPT_OUT_STANZA);
|
|
14433
14461
|
} catch {
|
|
14434
14462
|
return "failed";
|
|
14435
14463
|
}
|
|
@@ -14464,26 +14492,26 @@ function untrackVerityState() {
|
|
|
14464
14492
|
}
|
|
14465
14493
|
|
|
14466
14494
|
// src/lib/safe-path.ts
|
|
14467
|
-
var
|
|
14468
|
-
var
|
|
14495
|
+
var import_node_fs14 = require("node:fs");
|
|
14496
|
+
var import_node_path13 = require("node:path");
|
|
14469
14497
|
function resolveInside(baseDir, candidate) {
|
|
14470
14498
|
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(
|
|
14499
|
+
if ((0, import_node_path13.isAbsolute)(candidate)) return null;
|
|
14500
|
+
const baseAbs = (0, import_node_path13.resolve)(baseDir);
|
|
14501
|
+
const full = (0, import_node_path13.resolve)(baseAbs, candidate);
|
|
14502
|
+
const baseSep = baseAbs.endsWith(import_node_path13.sep) ? baseAbs : baseAbs + import_node_path13.sep;
|
|
14475
14503
|
if (full !== baseAbs && !full.startsWith(baseSep)) return null;
|
|
14476
14504
|
try {
|
|
14477
|
-
if ((0,
|
|
14478
|
-
const realBase = (0,
|
|
14479
|
-
const realBaseSep = realBase.endsWith(
|
|
14505
|
+
if ((0, import_node_fs14.existsSync)(baseAbs)) {
|
|
14506
|
+
const realBase = (0, import_node_fs14.realpathSync)(baseAbs);
|
|
14507
|
+
const realBaseSep = realBase.endsWith(import_node_path13.sep) ? realBase : realBase + import_node_path13.sep;
|
|
14480
14508
|
let probe = full;
|
|
14481
|
-
while (!(0,
|
|
14482
|
-
const parent = (0,
|
|
14509
|
+
while (!(0, import_node_fs14.existsSync)(probe)) {
|
|
14510
|
+
const parent = (0, import_node_path13.dirname)(probe);
|
|
14483
14511
|
if (parent === probe) break;
|
|
14484
14512
|
probe = parent;
|
|
14485
14513
|
}
|
|
14486
|
-
const realProbe = (0,
|
|
14514
|
+
const realProbe = (0, import_node_fs14.realpathSync)(probe);
|
|
14487
14515
|
if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
|
|
14488
14516
|
}
|
|
14489
14517
|
} catch {
|
|
@@ -14491,6 +14519,42 @@ function resolveInside(baseDir, candidate) {
|
|
|
14491
14519
|
}
|
|
14492
14520
|
return full;
|
|
14493
14521
|
}
|
|
14522
|
+
var O_NOFOLLOW = typeof import_node_fs14.constants.O_NOFOLLOW === "number" ? import_node_fs14.constants.O_NOFOLLOW : 0;
|
|
14523
|
+
function readFileInside(baseDir, candidate, maxBytes) {
|
|
14524
|
+
const full = resolveInside(baseDir, candidate);
|
|
14525
|
+
if (!full) return null;
|
|
14526
|
+
let realParent;
|
|
14527
|
+
let realBase;
|
|
14528
|
+
try {
|
|
14529
|
+
realParent = (0, import_node_fs14.realpathSync)((0, import_node_path13.dirname)(full));
|
|
14530
|
+
realBase = (0, import_node_fs14.realpathSync)((0, import_node_path13.resolve)(baseDir));
|
|
14531
|
+
} catch {
|
|
14532
|
+
return null;
|
|
14533
|
+
}
|
|
14534
|
+
const realBaseSep = realBase.endsWith(import_node_path13.sep) ? realBase : realBase + import_node_path13.sep;
|
|
14535
|
+
if (realParent !== realBase && !realParent.startsWith(realBaseSep)) return null;
|
|
14536
|
+
const target = (0, import_node_path13.join)(realParent, (0, import_node_path13.basename)(full));
|
|
14537
|
+
let fd = null;
|
|
14538
|
+
try {
|
|
14539
|
+
fd = (0, import_node_fs14.openSync)(target, import_node_fs14.constants.O_RDONLY | O_NOFOLLOW);
|
|
14540
|
+
const st = (0, import_node_fs14.fstatSync)(fd);
|
|
14541
|
+
if (!st.isFile()) return null;
|
|
14542
|
+
const cap = Math.min(maxBytes, st.size);
|
|
14543
|
+
if (cap <= 0) return "";
|
|
14544
|
+
const buf = Buffer.alloc(cap);
|
|
14545
|
+
const bytesRead = (0, import_node_fs14.readSync)(fd, buf, 0, cap, 0);
|
|
14546
|
+
return buf.subarray(0, bytesRead).toString("utf-8");
|
|
14547
|
+
} catch {
|
|
14548
|
+
return null;
|
|
14549
|
+
} finally {
|
|
14550
|
+
if (fd !== null) {
|
|
14551
|
+
try {
|
|
14552
|
+
(0, import_node_fs14.closeSync)(fd);
|
|
14553
|
+
} catch {
|
|
14554
|
+
}
|
|
14555
|
+
}
|
|
14556
|
+
}
|
|
14557
|
+
}
|
|
14494
14558
|
|
|
14495
14559
|
// src/lib/glob-match.ts
|
|
14496
14560
|
function globToRegex(glob) {
|
|
@@ -14568,32 +14632,32 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
|
|
|
14568
14632
|
async function ensureMemoryDir() {
|
|
14569
14633
|
await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
|
|
14570
14634
|
for (const domain of DOMAINS2) {
|
|
14571
|
-
await (0, import_promises9.mkdir)((0,
|
|
14635
|
+
await (0, import_promises9.mkdir)((0, import_node_path14.join)(memoryDir2(), domain), { recursive: true });
|
|
14572
14636
|
}
|
|
14573
|
-
if (!(0,
|
|
14574
|
-
await (0, import_promises9.writeFile)((0,
|
|
14637
|
+
if (!(0, import_node_fs15.existsSync)((0, import_node_path14.join)(memoryDir2(), "SCHEMA.md"))) {
|
|
14638
|
+
await (0, import_promises9.writeFile)((0, import_node_path14.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
|
|
14575
14639
|
}
|
|
14576
|
-
if (!(0,
|
|
14577
|
-
await (0, import_promises9.writeFile)((0,
|
|
14640
|
+
if (!(0, import_node_fs15.existsSync)((0, import_node_path14.join)(memoryDir2(), "index.md"))) {
|
|
14641
|
+
await (0, import_promises9.writeFile)((0, import_node_path14.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
|
|
14578
14642
|
}
|
|
14579
|
-
if (!(0,
|
|
14580
|
-
await (0, import_promises9.writeFile)((0,
|
|
14643
|
+
if (!(0, import_node_fs15.existsSync)((0, import_node_path14.join)(memoryDir2(), "log.md"))) {
|
|
14644
|
+
await (0, import_promises9.writeFile)((0, import_node_path14.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
|
|
14581
14645
|
}
|
|
14582
14646
|
}
|
|
14583
14647
|
async function buildManifest() {
|
|
14584
|
-
if (!(0,
|
|
14648
|
+
if (!(0, import_node_fs15.existsSync)(memoryDir2())) {
|
|
14585
14649
|
return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
|
|
14586
14650
|
}
|
|
14587
14651
|
const nodes = [];
|
|
14588
14652
|
for (const domain of DOMAINS2) {
|
|
14589
|
-
const domainDir = (0,
|
|
14590
|
-
if (!(0,
|
|
14653
|
+
const domainDir = (0, import_node_path14.join)(memoryDir2(), domain);
|
|
14654
|
+
if (!(0, import_node_fs15.existsSync)(domainDir)) continue;
|
|
14591
14655
|
try {
|
|
14592
14656
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
14593
14657
|
for (const file of files) {
|
|
14594
14658
|
if (!file.endsWith(".md")) continue;
|
|
14595
14659
|
const filePath = `${domain}/${file}`;
|
|
14596
|
-
const fullPath = (0,
|
|
14660
|
+
const fullPath = (0, import_node_path14.join)(memoryDir2(), filePath);
|
|
14597
14661
|
try {
|
|
14598
14662
|
const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
14599
14663
|
const hash = (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
@@ -14606,13 +14670,13 @@ async function buildManifest() {
|
|
|
14606
14670
|
}
|
|
14607
14671
|
let indexHash = null;
|
|
14608
14672
|
try {
|
|
14609
|
-
const indexContent = await (0, import_promises9.readFile)((0,
|
|
14673
|
+
const indexContent = await (0, import_promises9.readFile)((0, import_node_path14.join)(memoryDir2(), "index.md"), "utf-8");
|
|
14610
14674
|
indexHash = `sha256:${(0, import_node_crypto3.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
|
|
14611
14675
|
} catch {
|
|
14612
14676
|
}
|
|
14613
14677
|
let logLength = 0;
|
|
14614
14678
|
try {
|
|
14615
|
-
const logContent = await (0, import_promises9.readFile)((0,
|
|
14679
|
+
const logContent = await (0, import_promises9.readFile)((0, import_node_path14.join)(memoryDir2(), "log.md"), "utf-8");
|
|
14616
14680
|
logLength = logContent.split("\n").length;
|
|
14617
14681
|
} catch {
|
|
14618
14682
|
}
|
|
@@ -14623,15 +14687,15 @@ function hashContent(content) {
|
|
|
14623
14687
|
}
|
|
14624
14688
|
async function readOnDiskNodes() {
|
|
14625
14689
|
const out = /* @__PURE__ */ new Map();
|
|
14626
|
-
if (!(0,
|
|
14690
|
+
if (!(0, import_node_fs15.existsSync)(memoryDir2())) return out;
|
|
14627
14691
|
for (const domain of DOMAINS2) {
|
|
14628
|
-
const domainDir = (0,
|
|
14629
|
-
if (!(0,
|
|
14692
|
+
const domainDir = (0, import_node_path14.join)(memoryDir2(), domain);
|
|
14693
|
+
if (!(0, import_node_fs15.existsSync)(domainDir)) continue;
|
|
14630
14694
|
try {
|
|
14631
14695
|
for (const file of await (0, import_promises9.readdir)(domainDir)) {
|
|
14632
14696
|
if (!file.endsWith(".md")) continue;
|
|
14633
14697
|
try {
|
|
14634
|
-
out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0,
|
|
14698
|
+
out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path14.join)(domainDir, file), "utf-8")));
|
|
14635
14699
|
} catch {
|
|
14636
14700
|
}
|
|
14637
14701
|
}
|
|
@@ -14668,7 +14732,7 @@ async function recordSyncedNodePaths() {
|
|
|
14668
14732
|
}
|
|
14669
14733
|
}
|
|
14670
14734
|
async function writeFileAtomic(path, content) {
|
|
14671
|
-
await (0, import_promises9.mkdir)((0,
|
|
14735
|
+
await (0, import_promises9.mkdir)((0, import_node_path14.dirname)(path), { recursive: true });
|
|
14672
14736
|
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
14673
14737
|
await (0, import_promises9.writeFile)(tmp, content);
|
|
14674
14738
|
await (0, import_promises9.rename)(tmp, path);
|
|
@@ -14682,8 +14746,8 @@ async function computeEditedNodeUploads() {
|
|
|
14682
14746
|
const uploads = [];
|
|
14683
14747
|
for (const [path, prevHash] of prev) {
|
|
14684
14748
|
if (prevHash == null) continue;
|
|
14685
|
-
const full = (0,
|
|
14686
|
-
if (!(0,
|
|
14749
|
+
const full = (0, import_node_path14.join)(memoryDir2(), path);
|
|
14750
|
+
if (!(0, import_node_fs15.existsSync)(full)) continue;
|
|
14687
14751
|
let content;
|
|
14688
14752
|
try {
|
|
14689
14753
|
content = await (0, import_promises9.readFile)(full, "utf-8");
|
|
@@ -14727,8 +14791,8 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
14727
14791
|
const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
|
|
14728
14792
|
for (const n of notes) logLines.push(` - ${n}`);
|
|
14729
14793
|
try {
|
|
14730
|
-
const existing = (0,
|
|
14731
|
-
await (0, import_promises9.writeFile)((0,
|
|
14794
|
+
const existing = (0, import_node_fs15.existsSync)((0, import_node_path14.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path14.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
|
|
14795
|
+
await (0, import_promises9.writeFile)((0, import_node_path14.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
|
|
14732
14796
|
} catch {
|
|
14733
14797
|
}
|
|
14734
14798
|
if (opts.baseline === "written") await mergeSyncBaseline(synced);
|
|
@@ -14738,7 +14802,7 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
14738
14802
|
async function mergeSyncBaseline(entries) {
|
|
14739
14803
|
if (entries.size === 0) return;
|
|
14740
14804
|
try {
|
|
14741
|
-
if ((0,
|
|
14805
|
+
if ((0, import_node_fs15.existsSync)(syncStateFile())) {
|
|
14742
14806
|
try {
|
|
14743
14807
|
JSON.parse(await (0, import_promises9.readFile)(syncStateFile(), "utf-8"));
|
|
14744
14808
|
} catch {
|
|
@@ -14766,7 +14830,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
14766
14830
|
notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
|
|
14767
14831
|
}
|
|
14768
14832
|
}
|
|
14769
|
-
if ((0,
|
|
14833
|
+
if ((0, import_node_fs15.existsSync)(fullPath)) {
|
|
14770
14834
|
let existing = "";
|
|
14771
14835
|
try {
|
|
14772
14836
|
existing = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
@@ -14782,7 +14846,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
14782
14846
|
notes.push(`${write.path}: updated from server (untouched here since the server delivered it)`);
|
|
14783
14847
|
}
|
|
14784
14848
|
}
|
|
14785
|
-
await (0, import_promises9.mkdir)((0,
|
|
14849
|
+
await (0, import_promises9.mkdir)((0, import_node_path14.dirname)(fullPath), { recursive: true });
|
|
14786
14850
|
await (0, import_promises9.writeFile)(fullPath, content);
|
|
14787
14851
|
return { written: true, syncedHash: hashContent(content), notes };
|
|
14788
14852
|
}
|
|
@@ -14823,8 +14887,8 @@ async function regenerateIndex() {
|
|
|
14823
14887
|
];
|
|
14824
14888
|
let totalNodes = 0;
|
|
14825
14889
|
for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
|
|
14826
|
-
const domainDir = (0,
|
|
14827
|
-
if (!(0,
|
|
14890
|
+
const domainDir = (0, import_node_path14.join)(memoryDir2(), domain);
|
|
14891
|
+
if (!(0, import_node_fs15.existsSync)(domainDir)) continue;
|
|
14828
14892
|
try {
|
|
14829
14893
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
14830
14894
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
@@ -14834,7 +14898,7 @@ async function regenerateIndex() {
|
|
|
14834
14898
|
for (const file of mdFiles.sort()) {
|
|
14835
14899
|
const slug = file.replace(/\.md$/, "");
|
|
14836
14900
|
try {
|
|
14837
|
-
const content = await (0, import_promises9.readFile)((0,
|
|
14901
|
+
const content = await (0, import_promises9.readFile)((0, import_node_path14.join)(domainDir, file), "utf-8");
|
|
14838
14902
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
14839
14903
|
const kind = pickFrontmatter(content, "kind") ?? "-";
|
|
14840
14904
|
const confidence = pickFrontmatter(content, "confidence");
|
|
@@ -14858,7 +14922,7 @@ async function regenerateIndex() {
|
|
|
14858
14922
|
lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
|
|
14859
14923
|
}
|
|
14860
14924
|
const next = lines.join("\n") + "\n";
|
|
14861
|
-
const indexPath = (0,
|
|
14925
|
+
const indexPath = (0, import_node_path14.join)(memoryDir2(), "index.md");
|
|
14862
14926
|
let existing = null;
|
|
14863
14927
|
try {
|
|
14864
14928
|
existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
|
|
@@ -15255,9 +15319,9 @@ function hasLegacyMemoryBlock(text) {
|
|
|
15255
15319
|
return findMarker(text, LEGACY_MD_START) !== -1;
|
|
15256
15320
|
}
|
|
15257
15321
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
15258
|
-
const claudeMdPath = (0,
|
|
15322
|
+
const claudeMdPath = (0, import_node_path14.join)(cwd, "CLAUDE.md");
|
|
15259
15323
|
let existing = "";
|
|
15260
|
-
if ((0,
|
|
15324
|
+
if ((0, import_node_fs15.existsSync)(claudeMdPath)) {
|
|
15261
15325
|
existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
|
|
15262
15326
|
}
|
|
15263
15327
|
let startTag = CLAUDE_MD_START;
|
|
@@ -15398,9 +15462,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
|
|
|
15398
15462
|
`;
|
|
15399
15463
|
|
|
15400
15464
|
// src/lib/dossier-session.ts
|
|
15401
|
-
var
|
|
15465
|
+
var import_node_fs20 = require("node:fs");
|
|
15402
15466
|
var import_node_crypto7 = require("node:crypto");
|
|
15403
|
-
var
|
|
15467
|
+
var import_node_path17 = require("node:path");
|
|
15404
15468
|
|
|
15405
15469
|
// src/lib/pending-repeat.ts
|
|
15406
15470
|
var STOP = /* @__PURE__ */ new Set([
|
|
@@ -15505,8 +15569,8 @@ function statementAnchorKey(file, patternId) {
|
|
|
15505
15569
|
|
|
15506
15570
|
// src/lib/dossier/log.ts
|
|
15507
15571
|
var import_node_crypto4 = require("node:crypto");
|
|
15508
|
-
var
|
|
15509
|
-
var
|
|
15572
|
+
var import_node_fs16 = require("node:fs");
|
|
15573
|
+
var import_node_path15 = require("node:path");
|
|
15510
15574
|
var CRC_TABLE = (() => {
|
|
15511
15575
|
const t = new Int32Array(256);
|
|
15512
15576
|
for (let i = 0; i < 256; i++) {
|
|
@@ -15525,13 +15589,13 @@ function crc32(s) {
|
|
|
15525
15589
|
function openDossier(identity) {
|
|
15526
15590
|
try {
|
|
15527
15591
|
const dir = dossierDir(identity);
|
|
15528
|
-
(0,
|
|
15592
|
+
(0, import_node_fs16.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
15529
15593
|
return {
|
|
15530
15594
|
dir,
|
|
15531
15595
|
identity,
|
|
15532
|
-
eventsPath: (0,
|
|
15533
|
-
foldPath: (0,
|
|
15534
|
-
rotatedDir: (0,
|
|
15596
|
+
eventsPath: (0, import_node_path15.join)(dir, "events.jsonl"),
|
|
15597
|
+
foldPath: (0, import_node_path15.join)(dir, "fold.json"),
|
|
15598
|
+
rotatedDir: (0, import_node_path15.join)(dir, "rotated")
|
|
15535
15599
|
};
|
|
15536
15600
|
} catch {
|
|
15537
15601
|
return null;
|
|
@@ -15593,7 +15657,7 @@ function appendEvent(d, ev) {
|
|
|
15593
15657
|
at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
15594
15658
|
...ev
|
|
15595
15659
|
});
|
|
15596
|
-
(0,
|
|
15660
|
+
(0, import_node_fs16.appendFileSync)(d.eventsPath, line, { mode: 384 });
|
|
15597
15661
|
return true;
|
|
15598
15662
|
} catch {
|
|
15599
15663
|
return false;
|
|
@@ -15601,14 +15665,14 @@ function appendEvent(d, ev) {
|
|
|
15601
15665
|
}
|
|
15602
15666
|
function rotateIfNeeded2(d) {
|
|
15603
15667
|
try {
|
|
15604
|
-
if (!(0,
|
|
15605
|
-
if ((0,
|
|
15606
|
-
(0,
|
|
15607
|
-
(0,
|
|
15608
|
-
const kept = (0,
|
|
15668
|
+
if (!(0, import_node_fs16.existsSync)(d.eventsPath)) return;
|
|
15669
|
+
if ((0, import_node_fs16.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
|
|
15670
|
+
(0, import_node_fs16.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
|
|
15671
|
+
(0, import_node_fs16.renameSync)(d.eventsPath, (0, import_node_path15.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
|
|
15672
|
+
const kept = (0, import_node_fs16.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
15609
15673
|
for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
|
|
15610
15674
|
try {
|
|
15611
|
-
(0,
|
|
15675
|
+
(0, import_node_fs16.renameSync)((0, import_node_path15.join)(d.rotatedDir, stale), (0, import_node_path15.join)(d.rotatedDir, `${stale}.pruned`));
|
|
15612
15676
|
} catch {
|
|
15613
15677
|
}
|
|
15614
15678
|
}
|
|
@@ -15618,8 +15682,8 @@ function rotateIfNeeded2(d) {
|
|
|
15618
15682
|
|
|
15619
15683
|
// src/lib/dossier/fold-dossier.ts
|
|
15620
15684
|
var import_node_crypto5 = require("node:crypto");
|
|
15621
|
-
var
|
|
15622
|
-
var
|
|
15685
|
+
var import_node_fs17 = require("node:fs");
|
|
15686
|
+
var import_node_path16 = require("node:path");
|
|
15623
15687
|
var EMPTY_CAPABILITIES = () => ({
|
|
15624
15688
|
human_reachable: { value: "unknown", tier: "unknown" },
|
|
15625
15689
|
authorship_observability: { value: "unknown", tier: "unknown" },
|
|
@@ -15670,12 +15734,12 @@ function foldDossier(d, opts = {}) {
|
|
|
15670
15734
|
}
|
|
15671
15735
|
};
|
|
15672
15736
|
try {
|
|
15673
|
-
if ((0,
|
|
15674
|
-
const files = (0,
|
|
15737
|
+
if ((0, import_node_fs17.existsSync)(d.rotatedDir)) {
|
|
15738
|
+
const files = (0, import_node_fs17.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
15675
15739
|
state.meta.rotations = files.length;
|
|
15676
15740
|
for (const f of files) {
|
|
15677
15741
|
try {
|
|
15678
|
-
ingest((0,
|
|
15742
|
+
ingest((0, import_node_fs17.readFileSync)((0, import_node_path16.join)(d.rotatedDir, f), "utf8"));
|
|
15679
15743
|
} catch {
|
|
15680
15744
|
state.meta.dropped_lines++;
|
|
15681
15745
|
}
|
|
@@ -15684,9 +15748,9 @@ function foldDossier(d, opts = {}) {
|
|
|
15684
15748
|
} catch {
|
|
15685
15749
|
}
|
|
15686
15750
|
try {
|
|
15687
|
-
if ((0,
|
|
15688
|
-
state.meta.upto_offset = (0,
|
|
15689
|
-
ingest((0,
|
|
15751
|
+
if ((0, import_node_fs17.existsSync)(d.eventsPath)) {
|
|
15752
|
+
state.meta.upto_offset = (0, import_node_fs17.statSync)(d.eventsPath).size;
|
|
15753
|
+
ingest((0, import_node_fs17.readFileSync)(d.eventsPath, "utf8"));
|
|
15690
15754
|
}
|
|
15691
15755
|
} catch {
|
|
15692
15756
|
}
|
|
@@ -15957,7 +16021,7 @@ function applyBounds(state, input) {
|
|
|
15957
16021
|
}
|
|
15958
16022
|
|
|
15959
16023
|
// src/lib/dossier/cache.ts
|
|
15960
|
-
var
|
|
16024
|
+
var import_node_fs18 = require("node:fs");
|
|
15961
16025
|
function compactState(s) {
|
|
15962
16026
|
const ms = (iso) => Date.parse(iso) || 0;
|
|
15963
16027
|
return {
|
|
@@ -16086,20 +16150,20 @@ function encodeState(s) {
|
|
|
16086
16150
|
function writeFoldCache(d, state) {
|
|
16087
16151
|
try {
|
|
16088
16152
|
const tmp = `${d.foldPath}.${process.pid}.tmp`;
|
|
16089
|
-
(0,
|
|
16090
|
-
(0,
|
|
16153
|
+
(0, import_node_fs18.writeFileSync)(tmp, encodeState(state), { mode: 384 });
|
|
16154
|
+
(0, import_node_fs18.renameSync)(tmp, d.foldPath);
|
|
16091
16155
|
} catch {
|
|
16092
16156
|
}
|
|
16093
16157
|
}
|
|
16094
16158
|
function readFoldCache(d) {
|
|
16095
16159
|
try {
|
|
16096
|
-
if (!(0,
|
|
16097
|
-
const raw = JSON.parse((0,
|
|
16160
|
+
if (!(0, import_node_fs18.existsSync)(d.foldPath)) return null;
|
|
16161
|
+
const raw = JSON.parse((0, import_node_fs18.readFileSync)(d.foldPath, "utf8"));
|
|
16098
16162
|
if (raw?.v !== 1) return null;
|
|
16099
16163
|
const cached2 = expandState(raw);
|
|
16100
16164
|
if (!cached2?.meta) return null;
|
|
16101
|
-
const size = (0,
|
|
16102
|
-
const rotations = (0,
|
|
16165
|
+
const size = (0, import_node_fs18.existsSync)(d.eventsPath) ? (0, import_node_fs18.statSync)(d.eventsPath).size : 0;
|
|
16166
|
+
const rotations = (0, import_node_fs18.existsSync)(d.rotatedDir) ? (0, import_node_fs18.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
|
|
16103
16167
|
if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
|
|
16104
16168
|
return cached2;
|
|
16105
16169
|
} catch {
|
|
@@ -16150,13 +16214,13 @@ function assessContinuity(i) {
|
|
|
16150
16214
|
|
|
16151
16215
|
// src/lib/dossier/reanchor.ts
|
|
16152
16216
|
var import_node_crypto6 = require("node:crypto");
|
|
16153
|
-
var
|
|
16217
|
+
var import_node_fs19 = require("node:fs");
|
|
16154
16218
|
function lineSha(text) {
|
|
16155
16219
|
return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
|
|
16156
16220
|
}
|
|
16157
16221
|
function fileHash(path) {
|
|
16158
16222
|
try {
|
|
16159
|
-
return (0, import_node_crypto6.createHash)("sha256").update((0,
|
|
16223
|
+
return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs19.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
|
|
16160
16224
|
} catch {
|
|
16161
16225
|
return null;
|
|
16162
16226
|
}
|
|
@@ -16528,20 +16592,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
|
|
|
16528
16592
|
let sessions = 0;
|
|
16529
16593
|
try {
|
|
16530
16594
|
const dir = treeDir(identity);
|
|
16531
|
-
if (!(0,
|
|
16532
|
-
for (const entry of (0,
|
|
16595
|
+
if (!(0, import_node_fs20.existsSync)(dir)) return { paths: [], sessions: 0 };
|
|
16596
|
+
for (const entry of (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true })) {
|
|
16533
16597
|
if (!entry.isDirectory()) continue;
|
|
16534
16598
|
if (entry.name === identity.sessionKey) continue;
|
|
16535
|
-
const log = (0,
|
|
16599
|
+
const log = (0, import_node_path17.join)(dir, entry.name, "events.jsonl");
|
|
16536
16600
|
try {
|
|
16537
|
-
if (!(0,
|
|
16538
|
-
if (now - (0,
|
|
16601
|
+
if (!(0, import_node_fs20.existsSync)(log)) continue;
|
|
16602
|
+
if (now - (0, import_node_fs20.statSync)(log).mtimeMs > windowMs) continue;
|
|
16539
16603
|
const sib = {
|
|
16540
|
-
dir: (0,
|
|
16604
|
+
dir: (0, import_node_path17.join)(dir, entry.name),
|
|
16541
16605
|
identity,
|
|
16542
16606
|
eventsPath: log,
|
|
16543
|
-
foldPath: (0,
|
|
16544
|
-
rotatedDir: (0,
|
|
16607
|
+
foldPath: (0, import_node_path17.join)(dir, entry.name, "fold.json"),
|
|
16608
|
+
rotatedDir: (0, import_node_path17.join)(dir, entry.name, "rotated")
|
|
16545
16609
|
};
|
|
16546
16610
|
const state = readFoldCache(sib) ?? foldDossier(sib);
|
|
16547
16611
|
sessions++;
|
|
@@ -16569,25 +16633,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
16569
16633
|
let removed = 0;
|
|
16570
16634
|
try {
|
|
16571
16635
|
const mine = dossierDir(identity);
|
|
16572
|
-
const userDir = (0,
|
|
16573
|
-
if (!(0,
|
|
16636
|
+
const userDir = (0, import_node_path17.dirname)((0, import_node_path17.dirname)(mine));
|
|
16637
|
+
if (!(0, import_node_fs20.existsSync)(userDir)) return 0;
|
|
16574
16638
|
const cutoff = Date.now() - maxAgeMs;
|
|
16575
|
-
for (const tree of (0,
|
|
16639
|
+
for (const tree of (0, import_node_fs20.readdirSync)(userDir, { withFileTypes: true })) {
|
|
16576
16640
|
if (!tree.isDirectory()) continue;
|
|
16577
|
-
const treePath = (0,
|
|
16641
|
+
const treePath = (0, import_node_path17.join)(userDir, tree.name);
|
|
16578
16642
|
let live = 0;
|
|
16579
|
-
for (const entry of (0,
|
|
16643
|
+
for (const entry of (0, import_node_fs20.readdirSync)(treePath, { withFileTypes: true })) {
|
|
16580
16644
|
if (!entry.isDirectory()) continue;
|
|
16581
|
-
const dir = (0,
|
|
16645
|
+
const dir = (0, import_node_path17.join)(treePath, entry.name);
|
|
16582
16646
|
if (dir === mine) {
|
|
16583
16647
|
live++;
|
|
16584
16648
|
continue;
|
|
16585
16649
|
}
|
|
16586
16650
|
try {
|
|
16587
|
-
const log = (0,
|
|
16588
|
-
const at = (0,
|
|
16651
|
+
const log = (0, import_node_path17.join)(dir, "events.jsonl");
|
|
16652
|
+
const at = (0, import_node_fs20.existsSync)(log) ? (0, import_node_fs20.statSync)(log).mtimeMs : (0, import_node_fs20.statSync)(dir).mtimeMs;
|
|
16589
16653
|
if (at < cutoff) {
|
|
16590
|
-
(0,
|
|
16654
|
+
(0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
|
|
16591
16655
|
removed++;
|
|
16592
16656
|
} else {
|
|
16593
16657
|
live++;
|
|
@@ -16597,7 +16661,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
16597
16661
|
}
|
|
16598
16662
|
if (live === 0) {
|
|
16599
16663
|
try {
|
|
16600
|
-
(0,
|
|
16664
|
+
(0, import_node_fs20.rmSync)(treePath, { recursive: false, force: false });
|
|
16601
16665
|
} catch {
|
|
16602
16666
|
}
|
|
16603
16667
|
}
|
|
@@ -16614,8 +16678,8 @@ function sessionDossier(token, sessionId) {
|
|
|
16614
16678
|
}
|
|
16615
16679
|
function hasActiveGoal(d) {
|
|
16616
16680
|
try {
|
|
16617
|
-
if (!(0,
|
|
16618
|
-
return (0,
|
|
16681
|
+
if (!(0, import_node_fs20.existsSync)(d.eventsPath)) return false;
|
|
16682
|
+
return (0, import_node_fs20.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
|
|
16619
16683
|
} catch {
|
|
16620
16684
|
return false;
|
|
16621
16685
|
}
|
|
@@ -16639,7 +16703,7 @@ function recordTurn(d, t) {
|
|
|
16639
16703
|
for (const a of t.authored) {
|
|
16640
16704
|
const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
|
|
16641
16705
|
const prior = t.known?.authored?.get(a.p);
|
|
16642
|
-
const hash = fileHash((0,
|
|
16706
|
+
const hash = fileHash((0, import_node_path17.join)(root, a.p));
|
|
16643
16707
|
const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
|
|
16644
16708
|
const adds = Math.max(0, a.a - (prior?.adds ?? 0));
|
|
16645
16709
|
const dels = Math.max(0, a.d - (prior?.dels ?? 0));
|
|
@@ -16672,7 +16736,7 @@ function recordTurn(d, t) {
|
|
|
16672
16736
|
}
|
|
16673
16737
|
const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
|
|
16674
16738
|
for (const u of t.unobserved) {
|
|
16675
|
-
const hash = fileHash((0,
|
|
16739
|
+
const hash = fileHash((0, import_node_path17.join)(root, u.p));
|
|
16676
16740
|
if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
|
|
16677
16741
|
appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
|
|
16678
16742
|
}
|
|
@@ -16707,8 +16771,8 @@ function recordVerdict(d, v) {
|
|
|
16707
16771
|
if (!sent.has(f.file)) continue;
|
|
16708
16772
|
if (!lines.has(f.file)) {
|
|
16709
16773
|
try {
|
|
16710
|
-
const abs = (0,
|
|
16711
|
-
lines.set(f.file, (0,
|
|
16774
|
+
const abs = (0, import_node_path17.join)(root, f.file);
|
|
16775
|
+
lines.set(f.file, (0, import_node_fs20.existsSync)(abs) ? (0, import_node_fs20.readFileSync)(abs, "utf8").split("\n") : null);
|
|
16712
16776
|
} catch {
|
|
16713
16777
|
lines.set(f.file, null);
|
|
16714
16778
|
}
|
|
@@ -16808,8 +16872,8 @@ function recallMemory(d, identity, opts) {
|
|
|
16808
16872
|
budgetBytes: opts.budgetBytes,
|
|
16809
16873
|
readFileLines: (file) => {
|
|
16810
16874
|
try {
|
|
16811
|
-
const abs = (0,
|
|
16812
|
-
return (0,
|
|
16875
|
+
const abs = (0, import_node_path17.join)(root, file);
|
|
16876
|
+
return (0, import_node_fs20.existsSync)(abs) ? (0, import_node_fs20.readFileSync)(abs, "utf8").split("\n") : null;
|
|
16813
16877
|
} catch {
|
|
16814
16878
|
return null;
|
|
16815
16879
|
}
|
|
@@ -16953,46 +17017,46 @@ async function fireClassify(prompt, sessionId, globals) {
|
|
|
16953
17017
|
}
|
|
16954
17018
|
|
|
16955
17019
|
// src/commands/lifecycle.ts
|
|
16956
|
-
var
|
|
16957
|
-
var
|
|
17020
|
+
var import_node_fs24 = require("node:fs");
|
|
17021
|
+
var import_node_path22 = require("node:path");
|
|
16958
17022
|
|
|
16959
17023
|
// src/lib/baseline.ts
|
|
16960
|
-
var
|
|
16961
|
-
var
|
|
17024
|
+
var import_node_fs23 = require("node:fs");
|
|
17025
|
+
var import_node_path21 = require("node:path");
|
|
16962
17026
|
var import_node_crypto9 = require("node:crypto");
|
|
16963
17027
|
|
|
16964
17028
|
// src/lib/snapshot.ts
|
|
16965
|
-
var
|
|
16966
|
-
var
|
|
17029
|
+
var import_node_fs22 = require("node:fs");
|
|
17030
|
+
var import_node_path20 = require("node:path");
|
|
16967
17031
|
var import_node_child_process7 = require("node:child_process");
|
|
16968
17032
|
|
|
16969
17033
|
// src/lib/files.ts
|
|
16970
|
-
var
|
|
17034
|
+
var import_node_path19 = require("node:path");
|
|
16971
17035
|
|
|
16972
17036
|
// src/lib/safe-read.ts
|
|
16973
|
-
var
|
|
16974
|
-
var
|
|
16975
|
-
var FLAGS =
|
|
17037
|
+
var import_node_fs21 = require("node:fs");
|
|
17038
|
+
var import_node_path18 = require("node:path");
|
|
17039
|
+
var FLAGS = import_node_fs21.constants;
|
|
16976
17040
|
var NOFOLLOW = FLAGS.O_NOFOLLOW;
|
|
16977
17041
|
var NONBLOCK = FLAGS.O_NONBLOCK;
|
|
16978
17042
|
function closeOpened(fd) {
|
|
16979
17043
|
try {
|
|
16980
|
-
(0,
|
|
17044
|
+
(0, import_node_fs21.closeSync)(fd);
|
|
16981
17045
|
} catch {
|
|
16982
17046
|
}
|
|
16983
17047
|
}
|
|
16984
17048
|
function isInsideRoot(realRoot, realPath) {
|
|
16985
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
17049
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path18.sep) ? realRoot : realRoot + import_node_path18.sep);
|
|
16986
17050
|
}
|
|
16987
17051
|
function sameOpenedFile(opened, current, nofollowAvailable) {
|
|
16988
17052
|
if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
|
|
16989
17053
|
return opened.ino === current.ino && opened.dev === current.dev;
|
|
16990
17054
|
}
|
|
16991
17055
|
function openRegularInRoot(root, path) {
|
|
16992
|
-
const full = (0,
|
|
17056
|
+
const full = (0, import_node_path18.isAbsolute)(path) ? path : (0, import_node_path18.join)(root, path);
|
|
16993
17057
|
let fd;
|
|
16994
17058
|
try {
|
|
16995
|
-
fd = (0,
|
|
17059
|
+
fd = (0, import_node_fs21.openSync)(full, import_node_fs21.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
|
|
16996
17060
|
} catch (err) {
|
|
16997
17061
|
const code = err.code;
|
|
16998
17062
|
if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
|
|
@@ -17000,18 +17064,18 @@ function openRegularInRoot(root, path) {
|
|
|
17000
17064
|
return { ok: false, reason: "unreadable" };
|
|
17001
17065
|
}
|
|
17002
17066
|
try {
|
|
17003
|
-
const opened = (0,
|
|
17067
|
+
const opened = (0, import_node_fs21.fstatSync)(fd, { bigint: true });
|
|
17004
17068
|
if (!opened.isFile()) {
|
|
17005
17069
|
closeOpened(fd);
|
|
17006
17070
|
return { ok: false, reason: "not-regular" };
|
|
17007
17071
|
}
|
|
17008
|
-
const realRoot =
|
|
17009
|
-
const realPath =
|
|
17072
|
+
const realRoot = import_node_fs21.realpathSync.native(root);
|
|
17073
|
+
const realPath = import_node_fs21.realpathSync.native(full);
|
|
17010
17074
|
if (!isInsideRoot(realRoot, realPath)) {
|
|
17011
17075
|
closeOpened(fd);
|
|
17012
17076
|
return { ok: false, reason: "outside-root" };
|
|
17013
17077
|
}
|
|
17014
|
-
const current = (0,
|
|
17078
|
+
const current = (0, import_node_fs21.statSync)(realPath, { bigint: true });
|
|
17015
17079
|
if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
|
|
17016
17080
|
closeOpened(fd);
|
|
17017
17081
|
return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
|
|
@@ -17033,7 +17097,7 @@ function readOpened(fd, size) {
|
|
|
17033
17097
|
const buffer = Buffer.alloc(size);
|
|
17034
17098
|
let offset = 0;
|
|
17035
17099
|
while (offset < size) {
|
|
17036
|
-
const n = (0,
|
|
17100
|
+
const n = (0, import_node_fs21.readSync)(fd, buffer, offset, size - offset, offset);
|
|
17037
17101
|
if (n === 0) break;
|
|
17038
17102
|
offset += n;
|
|
17039
17103
|
}
|
|
@@ -17127,7 +17191,7 @@ var LANG_MAP = {
|
|
|
17127
17191
|
mk: "make"
|
|
17128
17192
|
};
|
|
17129
17193
|
function detectLanguage(filepath) {
|
|
17130
|
-
const ext = (0,
|
|
17194
|
+
const ext = (0, import_node_path19.extname)(filepath).slice(1);
|
|
17131
17195
|
return LANG_MAP[ext] ?? ext;
|
|
17132
17196
|
}
|
|
17133
17197
|
function sortByMtime(files) {
|
|
@@ -17218,16 +17282,16 @@ function collectCodeDelta(files, opts) {
|
|
|
17218
17282
|
|
|
17219
17283
|
// src/lib/snapshot.ts
|
|
17220
17284
|
function generateSnapshotDiffs(files) {
|
|
17221
|
-
if (!(0,
|
|
17285
|
+
if (!(0, import_node_fs22.existsSync)(SNAPSHOT_DIR)) {
|
|
17222
17286
|
return { diffs: [], has_snapshots: false };
|
|
17223
17287
|
}
|
|
17224
17288
|
const diffs = [];
|
|
17225
17289
|
for (const file of files) {
|
|
17226
17290
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
17227
|
-
const snapshotPath = (0,
|
|
17291
|
+
const snapshotPath = (0, import_node_path20.join)(SNAPSHOT_DIR, file.path);
|
|
17228
17292
|
const language = file.language ?? detectLanguage(file.path);
|
|
17229
|
-
if ((0,
|
|
17230
|
-
const oldContent = (0,
|
|
17293
|
+
if ((0, import_node_fs22.existsSync)(snapshotPath)) {
|
|
17294
|
+
const oldContent = (0, import_node_fs22.readFileSync)(snapshotPath, "utf-8");
|
|
17231
17295
|
if (oldContent === file.content) continue;
|
|
17232
17296
|
const diff = computeDiff(oldContent, file.content, file.path);
|
|
17233
17297
|
if (diff) {
|
|
@@ -17252,20 +17316,20 @@ function saveSnapshots(files) {
|
|
|
17252
17316
|
const snapshotPaths = /* @__PURE__ */ new Set();
|
|
17253
17317
|
for (const file of files) {
|
|
17254
17318
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
17255
|
-
const snapshotPath = (0,
|
|
17319
|
+
const snapshotPath = (0, import_node_path20.join)(SNAPSHOT_DIR, file.path);
|
|
17256
17320
|
snapshotPaths.add(snapshotPath);
|
|
17257
|
-
(0,
|
|
17258
|
-
(0,
|
|
17321
|
+
(0, import_node_fs22.mkdirSync)((0, import_node_path20.dirname)(snapshotPath), { recursive: true });
|
|
17322
|
+
(0, import_node_fs22.writeFileSync)(snapshotPath, file.content);
|
|
17259
17323
|
}
|
|
17260
17324
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
17261
17325
|
}
|
|
17262
17326
|
function computeDiff(oldContent, newContent, filePath) {
|
|
17263
|
-
const tmpOld = (0,
|
|
17264
|
-
const tmpNew = (0,
|
|
17327
|
+
const tmpOld = (0, import_node_path20.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
17328
|
+
const tmpNew = (0, import_node_path20.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
17265
17329
|
try {
|
|
17266
|
-
(0,
|
|
17267
|
-
(0,
|
|
17268
|
-
(0,
|
|
17330
|
+
(0, import_node_fs22.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
17331
|
+
(0, import_node_fs22.writeFileSync)(tmpOld, oldContent);
|
|
17332
|
+
(0, import_node_fs22.writeFileSync)(tmpNew, newContent);
|
|
17269
17333
|
const result = (0, import_node_child_process7.execSync)(
|
|
17270
17334
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
17271
17335
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -17279,32 +17343,32 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
17279
17343
|
return null;
|
|
17280
17344
|
} finally {
|
|
17281
17345
|
try {
|
|
17282
|
-
(0,
|
|
17346
|
+
(0, import_node_fs22.unlinkSync)(tmpOld);
|
|
17283
17347
|
} catch {
|
|
17284
17348
|
}
|
|
17285
17349
|
try {
|
|
17286
|
-
(0,
|
|
17350
|
+
(0, import_node_fs22.unlinkSync)(tmpNew);
|
|
17287
17351
|
} catch {
|
|
17288
17352
|
}
|
|
17289
17353
|
}
|
|
17290
17354
|
}
|
|
17291
17355
|
function cleanStaleSnapshots(dir, keepSet) {
|
|
17292
|
-
if (!(0,
|
|
17356
|
+
if (!(0, import_node_fs22.existsSync)(dir)) return;
|
|
17293
17357
|
try {
|
|
17294
|
-
const entries = (0,
|
|
17358
|
+
const entries = (0, import_node_fs22.readdirSync)(dir, { withFileTypes: true });
|
|
17295
17359
|
for (const entry of entries) {
|
|
17296
17360
|
if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
|
|
17297
|
-
const fullPath = (0,
|
|
17361
|
+
const fullPath = (0, import_node_path20.join)(dir, entry.name);
|
|
17298
17362
|
if (entry.isDirectory()) {
|
|
17299
17363
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
17300
17364
|
try {
|
|
17301
|
-
const remaining = (0,
|
|
17302
|
-
if (remaining.length === 0) (0,
|
|
17365
|
+
const remaining = (0, import_node_fs22.readdirSync)(fullPath);
|
|
17366
|
+
if (remaining.length === 0) (0, import_node_fs22.rmdirSync)(fullPath);
|
|
17303
17367
|
} catch {
|
|
17304
17368
|
}
|
|
17305
17369
|
} else if (!keepSet.has(fullPath)) {
|
|
17306
17370
|
try {
|
|
17307
|
-
(0,
|
|
17371
|
+
(0, import_node_fs22.unlinkSync)(fullPath);
|
|
17308
17372
|
} catch {
|
|
17309
17373
|
}
|
|
17310
17374
|
}
|
|
@@ -17323,20 +17387,20 @@ function sessionKey(sessionId) {
|
|
|
17323
17387
|
return (0, import_node_crypto9.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
17324
17388
|
}
|
|
17325
17389
|
function sessionDir(key) {
|
|
17326
|
-
return (0,
|
|
17390
|
+
return (0, import_node_path21.join)(projectPath(BASELINE_DIR), key);
|
|
17327
17391
|
}
|
|
17328
17392
|
function manifestPath(dir) {
|
|
17329
|
-
return (0,
|
|
17393
|
+
return (0, import_node_path21.join)(dir, "manifest.json");
|
|
17330
17394
|
}
|
|
17331
17395
|
function mirrorPath(dir, repoRelPath) {
|
|
17332
|
-
return (0,
|
|
17396
|
+
return (0, import_node_path21.join)(dir, "files", repoRelPath);
|
|
17333
17397
|
}
|
|
17334
17398
|
var CARRY_FILE = `${BASELINE_DIR}/.carry`;
|
|
17335
17399
|
var CARRY_WINDOW_MS = 12e4;
|
|
17336
17400
|
function writeCarry(sessionId, headSha) {
|
|
17337
17401
|
try {
|
|
17338
|
-
(0,
|
|
17339
|
-
(0,
|
|
17402
|
+
(0, import_node_fs23.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
|
|
17403
|
+
(0, import_node_fs23.writeFileSync)(
|
|
17340
17404
|
projectPath(CARRY_FILE),
|
|
17341
17405
|
JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
|
|
17342
17406
|
);
|
|
@@ -17346,10 +17410,10 @@ function writeCarry(sessionId, headSha) {
|
|
|
17346
17410
|
function claimCarry(newKey) {
|
|
17347
17411
|
const carryPath = projectPath(CARRY_FILE);
|
|
17348
17412
|
try {
|
|
17349
|
-
if (!(0,
|
|
17350
|
-
const carry = JSON.parse((0,
|
|
17413
|
+
if (!(0, import_node_fs23.existsSync)(carryPath)) return null;
|
|
17414
|
+
const carry = JSON.parse((0, import_node_fs23.readFileSync)(carryPath, "utf-8"));
|
|
17351
17415
|
try {
|
|
17352
|
-
(0,
|
|
17416
|
+
(0, import_node_fs23.rmSync)(carryPath, { force: true });
|
|
17353
17417
|
} catch {
|
|
17354
17418
|
}
|
|
17355
17419
|
if (!carry?.from_key || typeof carry.ts !== "number") return null;
|
|
@@ -17360,11 +17424,11 @@ function claimCarry(newKey) {
|
|
|
17360
17424
|
if (!prior) return null;
|
|
17361
17425
|
const toDir = sessionDir(newKey);
|
|
17362
17426
|
try {
|
|
17363
|
-
(0,
|
|
17427
|
+
(0, import_node_fs23.rmSync)(toDir, { recursive: true, force: true });
|
|
17364
17428
|
} catch {
|
|
17365
17429
|
}
|
|
17366
|
-
(0,
|
|
17367
|
-
(0,
|
|
17430
|
+
(0, import_node_fs23.renameSync)(fromDir, toDir);
|
|
17431
|
+
(0, import_node_fs23.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
|
|
17368
17432
|
return readManifest(toDir);
|
|
17369
17433
|
} catch {
|
|
17370
17434
|
return null;
|
|
@@ -17388,21 +17452,21 @@ function captureBaseline(opts = {}) {
|
|
|
17388
17452
|
const head_sha = getCurrentCommit();
|
|
17389
17453
|
const dirty = getDirtyFiles();
|
|
17390
17454
|
try {
|
|
17391
|
-
(0,
|
|
17455
|
+
(0, import_node_fs23.rmSync)(dir, { recursive: true, force: true });
|
|
17392
17456
|
} catch {
|
|
17393
17457
|
}
|
|
17394
|
-
const filesDir = (0,
|
|
17458
|
+
const filesDir = (0, import_node_path21.join)(dir, "files");
|
|
17395
17459
|
const mirrored = [];
|
|
17396
17460
|
try {
|
|
17397
|
-
(0,
|
|
17461
|
+
(0, import_node_fs23.mkdirSync)(filesDir, { recursive: true });
|
|
17398
17462
|
for (const p of dirty) {
|
|
17399
17463
|
if (p.includes("..")) continue;
|
|
17400
17464
|
const content = safeReadForMirror(projectPath(p));
|
|
17401
17465
|
if (content === null) continue;
|
|
17402
17466
|
const dest = mirrorPath(dir, p);
|
|
17403
17467
|
try {
|
|
17404
|
-
(0,
|
|
17405
|
-
(0,
|
|
17468
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path21.dirname)(dest), { recursive: true });
|
|
17469
|
+
(0, import_node_fs23.writeFileSync)(dest, content);
|
|
17406
17470
|
mirrored.push(p);
|
|
17407
17471
|
} catch {
|
|
17408
17472
|
}
|
|
@@ -17417,8 +17481,8 @@ function captureBaseline(opts = {}) {
|
|
|
17417
17481
|
version: BASELINE_VERSION
|
|
17418
17482
|
};
|
|
17419
17483
|
try {
|
|
17420
|
-
(0,
|
|
17421
|
-
(0,
|
|
17484
|
+
(0, import_node_fs23.mkdirSync)(dir, { recursive: true });
|
|
17485
|
+
(0, import_node_fs23.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
|
|
17422
17486
|
} catch {
|
|
17423
17487
|
}
|
|
17424
17488
|
pruneOldBaselines();
|
|
@@ -17429,9 +17493,9 @@ function readBaseline(sessionId) {
|
|
|
17429
17493
|
}
|
|
17430
17494
|
function readManifest(dir) {
|
|
17431
17495
|
const mp = manifestPath(dir);
|
|
17432
|
-
if (!(0,
|
|
17496
|
+
if (!(0, import_node_fs23.existsSync)(mp)) return null;
|
|
17433
17497
|
try {
|
|
17434
|
-
const parsed = JSON.parse((0,
|
|
17498
|
+
const parsed = JSON.parse((0, import_node_fs23.readFileSync)(mp, "utf-8"));
|
|
17435
17499
|
if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
|
|
17436
17500
|
return null;
|
|
17437
17501
|
}
|
|
@@ -17462,9 +17526,9 @@ function preImage(repoRelPath, baseline) {
|
|
|
17462
17526
|
function resolvePreImage(repoRelPath, baseline) {
|
|
17463
17527
|
if (baseline.dirty_paths.includes(repoRelPath)) {
|
|
17464
17528
|
const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
|
|
17465
|
-
if ((0,
|
|
17529
|
+
if ((0, import_node_fs23.existsSync)(mp)) {
|
|
17466
17530
|
try {
|
|
17467
|
-
return { content: (0,
|
|
17531
|
+
return { content: (0, import_node_fs23.readFileSync)(mp, "utf-8"), existed: true };
|
|
17468
17532
|
} catch {
|
|
17469
17533
|
}
|
|
17470
17534
|
}
|
|
@@ -17509,8 +17573,8 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
17509
17573
|
const content = safeReadForMirror(projectPath(p));
|
|
17510
17574
|
if (content === null) continue;
|
|
17511
17575
|
const dest = mirrorPath(dir, p);
|
|
17512
|
-
(0,
|
|
17513
|
-
(0,
|
|
17576
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path21.dirname)(dest), { recursive: true });
|
|
17577
|
+
(0, import_node_fs23.writeFileSync)(dest, content);
|
|
17514
17578
|
dirty.add(p);
|
|
17515
17579
|
adopted++;
|
|
17516
17580
|
} catch {
|
|
@@ -17519,7 +17583,7 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
17519
17583
|
if (adopted === 0) return 0;
|
|
17520
17584
|
try {
|
|
17521
17585
|
const updated = { ...baseline, dirty_paths: [...dirty] };
|
|
17522
|
-
(0,
|
|
17586
|
+
(0, import_node_fs23.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
|
|
17523
17587
|
preImageCache.delete(baseline);
|
|
17524
17588
|
} catch {
|
|
17525
17589
|
return 0;
|
|
@@ -17530,7 +17594,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
17530
17594
|
const pre = preImage(repoRelPath, baseline);
|
|
17531
17595
|
let current;
|
|
17532
17596
|
try {
|
|
17533
|
-
current = (0,
|
|
17597
|
+
current = (0, import_node_fs23.readFileSync)(projectPath(repoRelPath), "utf-8");
|
|
17534
17598
|
} catch {
|
|
17535
17599
|
return pre.existed;
|
|
17536
17600
|
}
|
|
@@ -17539,8 +17603,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
17539
17603
|
}
|
|
17540
17604
|
function safeReadForMirror(absPath) {
|
|
17541
17605
|
try {
|
|
17542
|
-
if ((0,
|
|
17543
|
-
const buf = (0,
|
|
17606
|
+
if ((0, import_node_fs23.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
|
|
17607
|
+
const buf = (0, import_node_fs23.readFileSync)(absPath);
|
|
17544
17608
|
if (buf.includes(0)) return null;
|
|
17545
17609
|
return buf.toString("utf-8");
|
|
17546
17610
|
} catch {
|
|
@@ -17551,18 +17615,18 @@ function pruneOldBaselines() {
|
|
|
17551
17615
|
const root = projectPath(BASELINE_DIR);
|
|
17552
17616
|
let entries;
|
|
17553
17617
|
try {
|
|
17554
|
-
entries = (0,
|
|
17618
|
+
entries = (0, import_node_fs23.readdirSync)(root);
|
|
17555
17619
|
} catch {
|
|
17556
17620
|
return;
|
|
17557
17621
|
}
|
|
17558
17622
|
const now = Date.now();
|
|
17559
17623
|
for (const name of entries) {
|
|
17560
|
-
const dir = (0,
|
|
17624
|
+
const dir = (0, import_node_path21.join)(root, name);
|
|
17561
17625
|
const manifest = readManifest(dir);
|
|
17562
17626
|
if (!manifest) {
|
|
17563
17627
|
try {
|
|
17564
|
-
if (now - (0,
|
|
17565
|
-
(0,
|
|
17628
|
+
if (now - (0, import_node_fs23.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
|
|
17629
|
+
(0, import_node_fs23.rmSync)(dir, { recursive: true, force: true });
|
|
17566
17630
|
}
|
|
17567
17631
|
} catch {
|
|
17568
17632
|
}
|
|
@@ -17570,7 +17634,7 @@ function pruneOldBaselines() {
|
|
|
17570
17634
|
}
|
|
17571
17635
|
if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
|
|
17572
17636
|
try {
|
|
17573
|
-
(0,
|
|
17637
|
+
(0, import_node_fs23.rmSync)(dir, { recursive: true, force: true });
|
|
17574
17638
|
} catch {
|
|
17575
17639
|
}
|
|
17576
17640
|
}
|
|
@@ -17745,8 +17809,8 @@ function buildCompactionContext(session) {
|
|
|
17745
17809
|
commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
|
|
17746
17810
|
readFileLines: (file) => {
|
|
17747
17811
|
try {
|
|
17748
|
-
const abs = (0,
|
|
17749
|
-
return (0,
|
|
17812
|
+
const abs = (0, import_node_path22.join)(root, file);
|
|
17813
|
+
return (0, import_node_fs24.existsSync)(abs) ? (0, import_node_fs24.readFileSync)(abs, "utf8").split("\n") : null;
|
|
17750
17814
|
} catch {
|
|
17751
17815
|
return null;
|
|
17752
17816
|
}
|
|
@@ -17803,24 +17867,24 @@ async function readHookStdin() {
|
|
|
17803
17867
|
|
|
17804
17868
|
// src/commands/standard.ts
|
|
17805
17869
|
var import_promises13 = require("node:fs/promises");
|
|
17806
|
-
var
|
|
17870
|
+
var import_node_fs31 = require("node:fs");
|
|
17807
17871
|
var import_yaml3 = __toESM(require_dist());
|
|
17808
17872
|
|
|
17809
17873
|
// src/lib/synthesize.ts
|
|
17810
17874
|
var import_node_child_process9 = require("node:child_process");
|
|
17811
|
-
var
|
|
17875
|
+
var import_node_fs27 = require("node:fs");
|
|
17812
17876
|
var import_promises10 = require("node:fs/promises");
|
|
17813
|
-
var
|
|
17877
|
+
var import_node_path25 = require("node:path");
|
|
17814
17878
|
var import_yaml = __toESM(require_dist());
|
|
17815
17879
|
|
|
17816
17880
|
// src/lib/data-dir.ts
|
|
17817
|
-
var
|
|
17818
|
-
var
|
|
17881
|
+
var import_node_fs25 = require("node:fs");
|
|
17882
|
+
var import_node_path23 = require("node:path");
|
|
17819
17883
|
function resolveDataDir() {
|
|
17820
17884
|
const candidates2 = [
|
|
17821
|
-
(0,
|
|
17885
|
+
(0, import_node_path23.join)(__dirname, "..", "data"),
|
|
17822
17886
|
// installed: node_modules/@codacy/verity-cli/data
|
|
17823
|
-
(0,
|
|
17887
|
+
(0, import_node_path23.join)(__dirname, "..", "..", "data"),
|
|
17824
17888
|
// edge case: nested resolution
|
|
17825
17889
|
// THE COMMITTED SOURCE, for a source checkout that has not been built.
|
|
17826
17890
|
// cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
|
|
@@ -17829,14 +17893,14 @@ function resolveDataDir() {
|
|
|
17829
17893
|
// without this the synthesizer throws "Could not find Verity skill data"
|
|
17830
17894
|
// for every test and every `verity` run from source. Resolved from this
|
|
17831
17895
|
// module's own location, never the cwd: see the warning below.
|
|
17832
|
-
(0,
|
|
17896
|
+
(0, import_node_path23.join)(__dirname, "..", "..", "client"),
|
|
17833
17897
|
// bundled: cli/bin/ → ../../client
|
|
17834
|
-
(0,
|
|
17898
|
+
(0, import_node_path23.join)(__dirname, "..", "..", "..", "client"),
|
|
17835
17899
|
// tsx: cli/src/lib/ → ../../../client
|
|
17836
17900
|
...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
|
|
17837
17901
|
];
|
|
17838
17902
|
for (const candidate of candidates2) {
|
|
17839
|
-
if ((0,
|
|
17903
|
+
if ((0, import_node_fs25.existsSync)((0, import_node_path23.join)(candidate, "skills"))) {
|
|
17840
17904
|
return candidate;
|
|
17841
17905
|
}
|
|
17842
17906
|
}
|
|
@@ -17845,13 +17909,13 @@ function resolveDataDir() {
|
|
|
17845
17909
|
);
|
|
17846
17910
|
}
|
|
17847
17911
|
function setupDataPath(file) {
|
|
17848
|
-
return (0,
|
|
17912
|
+
return (0, import_node_path23.join)(resolveDataDir(), "skills", "verity-setup", file);
|
|
17849
17913
|
}
|
|
17850
17914
|
|
|
17851
17915
|
// src/lib/detect.ts
|
|
17852
17916
|
var import_node_child_process8 = require("node:child_process");
|
|
17853
|
-
var
|
|
17854
|
-
var
|
|
17917
|
+
var import_node_fs26 = require("node:fs");
|
|
17918
|
+
var import_node_path24 = require("node:path");
|
|
17855
17919
|
var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
17856
17920
|
"typescript",
|
|
17857
17921
|
"javascript",
|
|
@@ -17908,25 +17972,25 @@ function walk(root) {
|
|
|
17908
17972
|
if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
|
|
17909
17973
|
let entries;
|
|
17910
17974
|
try {
|
|
17911
|
-
entries = (0,
|
|
17975
|
+
entries = (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true });
|
|
17912
17976
|
} catch {
|
|
17913
17977
|
return;
|
|
17914
17978
|
}
|
|
17915
17979
|
for (const entry of entries) {
|
|
17916
17980
|
if (found.length >= WALK_MAX_FILES) return;
|
|
17917
17981
|
if (IGNORED_SEGMENTS.includes(entry.name)) continue;
|
|
17918
|
-
const full = (0,
|
|
17982
|
+
const full = (0, import_node_path24.join)(dir, entry.name);
|
|
17919
17983
|
if (entry.isDirectory()) visit(full, depth + 1);
|
|
17920
|
-
else if (entry.isFile()) found.push((0,
|
|
17984
|
+
else if (entry.isFile()) found.push((0, import_node_path24.relative)(root, full));
|
|
17921
17985
|
}
|
|
17922
17986
|
};
|
|
17923
17987
|
visit(root, 0);
|
|
17924
17988
|
return found;
|
|
17925
17989
|
}
|
|
17926
17990
|
function languageOf(path) {
|
|
17927
|
-
const name = (0,
|
|
17991
|
+
const name = (0, import_node_path24.basename)(path);
|
|
17928
17992
|
if (/^Dockerfile(\..+)?$/i.test(name)) return "dockerfile";
|
|
17929
|
-
if (!(0,
|
|
17993
|
+
if (!(0, import_node_path24.extname)(name)) return null;
|
|
17930
17994
|
const lang = detectLanguage(path);
|
|
17931
17995
|
return lang || null;
|
|
17932
17996
|
}
|
|
@@ -17983,7 +18047,7 @@ var TOOL_CONFIG_MARKERS = [
|
|
|
17983
18047
|
];
|
|
17984
18048
|
function readJson(path) {
|
|
17985
18049
|
try {
|
|
17986
|
-
return JSON.parse((0,
|
|
18050
|
+
return JSON.parse((0, import_node_fs26.readFileSync)(path, "utf-8"));
|
|
17987
18051
|
} catch {
|
|
17988
18052
|
return null;
|
|
17989
18053
|
}
|
|
@@ -18008,17 +18072,17 @@ function declaredDependencies(root, files) {
|
|
|
18008
18072
|
if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
|
|
18009
18073
|
}
|
|
18010
18074
|
};
|
|
18011
|
-
readPackageJson((0,
|
|
18012
|
-
const nested = files.filter((f) => f.includes("/") && (0,
|
|
18013
|
-
for (const rel of nested) readPackageJson((0,
|
|
18075
|
+
readPackageJson((0, import_node_path24.join)(root, "package.json"));
|
|
18076
|
+
const nested = files.filter((f) => f.includes("/") && (0, import_node_path24.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
|
|
18077
|
+
for (const rel of nested) readPackageJson((0, import_node_path24.join)(root, rel));
|
|
18014
18078
|
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,
|
|
18079
|
+
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path24.join)(root, f)),
|
|
18080
|
+
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path24.join)(root, f))
|
|
18017
18081
|
];
|
|
18018
18082
|
for (const path of pythonManifests) {
|
|
18019
|
-
if (!(0,
|
|
18083
|
+
if (!(0, import_node_fs26.existsSync)(path)) continue;
|
|
18020
18084
|
try {
|
|
18021
|
-
const text = (0,
|
|
18085
|
+
const text = (0, import_node_fs26.readFileSync)(path, "utf-8");
|
|
18022
18086
|
for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
|
|
18023
18087
|
for (const line of text.split("\n")) {
|
|
18024
18088
|
if (!/dependencies\s*=/.test(line)) continue;
|
|
@@ -18028,13 +18092,13 @@ function declaredDependencies(root, files) {
|
|
|
18028
18092
|
}
|
|
18029
18093
|
}
|
|
18030
18094
|
const goMods = [
|
|
18031
|
-
(0,
|
|
18032
|
-
...files.filter((f) => f.includes("/") && (0,
|
|
18095
|
+
(0, import_node_path24.join)(root, "go.mod"),
|
|
18096
|
+
...files.filter((f) => f.includes("/") && (0, import_node_path24.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path24.join)(root, f))
|
|
18033
18097
|
];
|
|
18034
18098
|
for (const path of goMods) {
|
|
18035
|
-
if (!(0,
|
|
18099
|
+
if (!(0, import_node_fs26.existsSync)(path)) continue;
|
|
18036
18100
|
try {
|
|
18037
|
-
const text = (0,
|
|
18101
|
+
const text = (0, import_node_fs26.readFileSync)(path, "utf-8");
|
|
18038
18102
|
for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
|
|
18039
18103
|
names2.push(m[1].replace(/^github\.com\//, ""));
|
|
18040
18104
|
}
|
|
@@ -18042,10 +18106,10 @@ function declaredDependencies(root, files) {
|
|
|
18042
18106
|
}
|
|
18043
18107
|
}
|
|
18044
18108
|
for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
|
|
18045
|
-
const path = (0,
|
|
18046
|
-
if (!(0,
|
|
18109
|
+
const path = (0, import_node_path24.join)(root, file);
|
|
18110
|
+
if (!(0, import_node_fs26.existsSync)(path)) continue;
|
|
18047
18111
|
try {
|
|
18048
|
-
const text = (0,
|
|
18112
|
+
const text = (0, import_node_fs26.readFileSync)(path, "utf-8");
|
|
18049
18113
|
for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
|
|
18050
18114
|
} catch {
|
|
18051
18115
|
}
|
|
@@ -18053,7 +18117,7 @@ function declaredDependencies(root, files) {
|
|
|
18053
18117
|
return names2;
|
|
18054
18118
|
}
|
|
18055
18119
|
function detectBuildSystem(root, files) {
|
|
18056
|
-
const has = (f) => (0,
|
|
18120
|
+
const has = (f) => (0, import_node_fs26.existsSync)((0, import_node_path24.join)(root, f)) || files.some((p) => (0, import_node_path24.basename)(p) === f);
|
|
18057
18121
|
if (has("pnpm-lock.yaml")) return "pnpm";
|
|
18058
18122
|
if (has("yarn.lock")) return "yarn";
|
|
18059
18123
|
if (has("bun.lock") || has("bun.lockb")) return "bun";
|
|
@@ -18070,8 +18134,8 @@ function detectBuildSystem(root, files) {
|
|
|
18070
18134
|
}
|
|
18071
18135
|
function detectArchitecture(root, files) {
|
|
18072
18136
|
const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
|
|
18073
|
-
if (workspaceMarkers.some((m) => (0,
|
|
18074
|
-
const pkg = readJson((0,
|
|
18137
|
+
if (workspaceMarkers.some((m) => (0, import_node_fs26.existsSync)((0, import_node_path24.join)(root, m)))) return "monorepo";
|
|
18138
|
+
const pkg = readJson((0, import_node_path24.join)(root, "package.json"));
|
|
18075
18139
|
if (pkg && "workspaces" in pkg) return "monorepo";
|
|
18076
18140
|
const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
|
|
18077
18141
|
const nested = manifests.filter((f) => f.includes("/"));
|
|
@@ -18093,10 +18157,10 @@ function measureAvgFileLength(root, files, languages) {
|
|
|
18093
18157
|
let total = 0;
|
|
18094
18158
|
let counted = 0;
|
|
18095
18159
|
for (let i = 0; i < candidates2.length; i += stride) {
|
|
18096
|
-
const path = (0,
|
|
18160
|
+
const path = (0, import_node_path24.join)(root, candidates2[i]);
|
|
18097
18161
|
try {
|
|
18098
|
-
if ((0,
|
|
18099
|
-
total += (0,
|
|
18162
|
+
if ((0, import_node_fs26.statSync)(path).size > 2 * 1024 * 1024) continue;
|
|
18163
|
+
total += (0, import_node_fs26.readFileSync)(path, "utf-8").split("\n").length;
|
|
18100
18164
|
counted++;
|
|
18101
18165
|
} catch {
|
|
18102
18166
|
}
|
|
@@ -18126,14 +18190,14 @@ function detectProject(root = repoRoot()) {
|
|
|
18126
18190
|
const existingToolConfigs = [];
|
|
18127
18191
|
for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
|
|
18128
18192
|
for (const marker of markers) {
|
|
18129
|
-
if ((0,
|
|
18193
|
+
if ((0, import_node_fs26.existsSync)((0, import_node_path24.join)(root, marker))) {
|
|
18130
18194
|
existingToolConfigs.push({ tool, path: `./${marker}` });
|
|
18131
18195
|
break;
|
|
18132
18196
|
}
|
|
18133
18197
|
}
|
|
18134
18198
|
}
|
|
18135
18199
|
return {
|
|
18136
|
-
projectName: (0,
|
|
18200
|
+
projectName: (0, import_node_path24.basename)(root),
|
|
18137
18201
|
languages,
|
|
18138
18202
|
languageCounts,
|
|
18139
18203
|
frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
|
|
@@ -18231,8 +18295,8 @@ ${closingNote(input.origin)}
|
|
|
18231
18295
|
|
|
18232
18296
|
// src/lib/synthesize.ts
|
|
18233
18297
|
function loadCatalog() {
|
|
18234
|
-
const catalog = (0, import_yaml.parse)((0,
|
|
18235
|
-
const template = (0, import_yaml.parse)((0,
|
|
18298
|
+
const catalog = (0, import_yaml.parse)((0, import_node_fs27.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
|
|
18299
|
+
const template = (0, import_yaml.parse)((0, import_node_fs27.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
|
|
18236
18300
|
return { catalog, template };
|
|
18237
18301
|
}
|
|
18238
18302
|
function selectTools(languages, intensity, catalog) {
|
|
@@ -18510,7 +18574,7 @@ function validatePatternIds() {
|
|
|
18510
18574
|
}
|
|
18511
18575
|
async function runSynthesis(opts) {
|
|
18512
18576
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18513
|
-
if ((0,
|
|
18577
|
+
if ((0, import_node_fs27.existsSync)(standardPath) && !opts.force) {
|
|
18514
18578
|
return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
|
|
18515
18579
|
}
|
|
18516
18580
|
const detected = opts.detected ?? detectProject();
|
|
@@ -18577,9 +18641,9 @@ async function correctVerityMdVersion(opts) {
|
|
|
18577
18641
|
origin: { kind: "synthesized", tools: opts.tools }
|
|
18578
18642
|
}));
|
|
18579
18643
|
}
|
|
18580
|
-
async function writeFileTo(
|
|
18581
|
-
const target = projectPath(
|
|
18582
|
-
await (0, import_promises10.mkdir)((0,
|
|
18644
|
+
async function writeFileTo(relative3, body) {
|
|
18645
|
+
const target = projectPath(relative3);
|
|
18646
|
+
await (0, import_promises10.mkdir)((0, import_node_path25.dirname)(target), { recursive: true });
|
|
18583
18647
|
await (0, import_promises10.writeFile)(target, body);
|
|
18584
18648
|
}
|
|
18585
18649
|
async function deriveConfigForStandard(standard) {
|
|
@@ -18638,11 +18702,11 @@ ${validation.detail}`);
|
|
|
18638
18702
|
|
|
18639
18703
|
// src/lib/setup-state.ts
|
|
18640
18704
|
var import_promises11 = require("node:fs/promises");
|
|
18641
|
-
var
|
|
18705
|
+
var import_node_fs28 = require("node:fs");
|
|
18642
18706
|
var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
|
|
18643
18707
|
async function readSetupState() {
|
|
18644
18708
|
const path = projectPath(SETUP_STATE_FILE);
|
|
18645
|
-
if (!(0,
|
|
18709
|
+
if (!(0, import_node_fs28.existsSync)(path)) return null;
|
|
18646
18710
|
try {
|
|
18647
18711
|
const parsed = JSON.parse(await (0, import_promises11.readFile)(path, "utf-8"));
|
|
18648
18712
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
@@ -18658,12 +18722,12 @@ async function writeSetupState(patch) {
|
|
|
18658
18722
|
}
|
|
18659
18723
|
|
|
18660
18724
|
// src/lib/push-setup.ts
|
|
18661
|
-
var
|
|
18725
|
+
var import_node_fs30 = require("node:fs");
|
|
18662
18726
|
var import_promises12 = require("node:fs/promises");
|
|
18663
18727
|
var import_yaml2 = __toESM(require_dist());
|
|
18664
18728
|
|
|
18665
18729
|
// src/lib/verityignore.ts
|
|
18666
|
-
var
|
|
18730
|
+
var import_node_fs29 = require("node:fs");
|
|
18667
18731
|
var EMPTY = { rules: [], securityOverlap: [], problems: [] };
|
|
18668
18732
|
var SECURITY_PROBES = [
|
|
18669
18733
|
".env",
|
|
@@ -18756,9 +18820,9 @@ function isIgnored3(ig, path) {
|
|
|
18756
18820
|
}
|
|
18757
18821
|
function loadVerityIgnore() {
|
|
18758
18822
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
18759
|
-
if (!(0,
|
|
18823
|
+
if (!(0, import_node_fs29.existsSync)(file)) return EMPTY;
|
|
18760
18824
|
try {
|
|
18761
|
-
return parseVerityIgnore((0,
|
|
18825
|
+
return parseVerityIgnore((0, import_node_fs29.readFileSync)(file, "utf-8"));
|
|
18762
18826
|
} catch {
|
|
18763
18827
|
return EMPTY;
|
|
18764
18828
|
}
|
|
@@ -18796,9 +18860,9 @@ function buildStandardUpload(standard, ignoreRaw) {
|
|
|
18796
18860
|
}
|
|
18797
18861
|
function readVerityIgnoreRaw() {
|
|
18798
18862
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
18799
|
-
if (!(0,
|
|
18863
|
+
if (!(0, import_node_fs29.existsSync)(file)) return null;
|
|
18800
18864
|
try {
|
|
18801
|
-
return (0,
|
|
18865
|
+
return (0, import_node_fs29.readFileSync)(file, "utf-8");
|
|
18802
18866
|
} catch {
|
|
18803
18867
|
return null;
|
|
18804
18868
|
}
|
|
@@ -18826,7 +18890,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
18826
18890
|
}
|
|
18827
18891
|
let standardVersion = null;
|
|
18828
18892
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18829
|
-
if (pushStandard && (0,
|
|
18893
|
+
if (pushStandard && (0, import_node_fs30.existsSync)(standardPath)) {
|
|
18830
18894
|
try {
|
|
18831
18895
|
const content = (0, import_yaml2.parse)(await (0, import_promises12.readFile)(standardPath, "utf-8"));
|
|
18832
18896
|
const upload = buildStandardUpload(content, readVerityIgnoreRaw());
|
|
@@ -18851,7 +18915,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
18851
18915
|
}
|
|
18852
18916
|
let configPushed = false;
|
|
18853
18917
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
18854
|
-
if (pushConfig && (0,
|
|
18918
|
+
if (pushConfig && (0, import_node_fs30.existsSync)(configPath)) {
|
|
18855
18919
|
try {
|
|
18856
18920
|
const content = JSON.parse(await (0, import_promises12.readFile)(configPath, "utf-8"));
|
|
18857
18921
|
const result = await apiRequest({
|
|
@@ -18883,7 +18947,7 @@ function registerStandardCommands(program2) {
|
|
|
18883
18947
|
const state = await readSetupState();
|
|
18884
18948
|
if (opts.configOnly) {
|
|
18885
18949
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18886
|
-
if (!(0,
|
|
18950
|
+
if (!(0, import_node_fs31.existsSync)(standardPath)) {
|
|
18887
18951
|
printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
|
|
18888
18952
|
process.exit(1);
|
|
18889
18953
|
}
|
|
@@ -19195,7 +19259,9 @@ function formatRunDetail(run2) {
|
|
|
19195
19259
|
if (f.description && f.description !== title) lines.push(` ${f.description}`);
|
|
19196
19260
|
const fix = f.fix?.description ?? f.suggestion;
|
|
19197
19261
|
if (fix) lines.push(` \u21B3 fix: ${fix}`);
|
|
19198
|
-
if (f.scope === "pre-existing")
|
|
19262
|
+
if (f.scope === "pre-existing") {
|
|
19263
|
+
lines.push(f.provenance === "caused-elsewhere" ? " (caused elsewhere \u2014 not by this change)" : " (pre-existing)");
|
|
19264
|
+
}
|
|
19199
19265
|
}
|
|
19200
19266
|
}
|
|
19201
19267
|
const pending = run2.pending_items ?? [];
|
|
@@ -19214,10 +19280,10 @@ function formatRunDetail(run2) {
|
|
|
19214
19280
|
}
|
|
19215
19281
|
|
|
19216
19282
|
// src/lib/ignore-declaration.ts
|
|
19217
|
-
var
|
|
19283
|
+
var import_node_fs33 = require("node:fs");
|
|
19218
19284
|
|
|
19219
19285
|
// src/lib/debounce.ts
|
|
19220
|
-
var
|
|
19286
|
+
var import_node_fs32 = require("node:fs");
|
|
19221
19287
|
var import_node_crypto10 = require("node:crypto");
|
|
19222
19288
|
function scopedFile(base, sessionId) {
|
|
19223
19289
|
if (!sessionId) return base;
|
|
@@ -19225,9 +19291,9 @@ function scopedFile(base, sessionId) {
|
|
|
19225
19291
|
}
|
|
19226
19292
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
19227
19293
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19228
|
-
if (!(0,
|
|
19294
|
+
if (!(0, import_node_fs32.existsSync)(file)) return null;
|
|
19229
19295
|
try {
|
|
19230
|
-
const lastTs = parseInt((0,
|
|
19296
|
+
const lastTs = parseInt((0, import_node_fs32.readFileSync)(file, "utf-8").trim(), 10);
|
|
19231
19297
|
const nowTs = Math.floor(Date.now() / 1e3);
|
|
19232
19298
|
const elapsed = nowTs - lastTs;
|
|
19233
19299
|
if (elapsed < debounceSeconds) {
|
|
@@ -19240,10 +19306,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
|
19240
19306
|
function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
19241
19307
|
if (bypassForRecentCommits) return null;
|
|
19242
19308
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19243
|
-
if (!(0,
|
|
19309
|
+
if (!(0, import_node_fs32.existsSync)(file)) return null;
|
|
19244
19310
|
let debounceTime;
|
|
19245
19311
|
try {
|
|
19246
|
-
debounceTime = (0,
|
|
19312
|
+
debounceTime = (0, import_node_fs32.statSync)(file).mtimeMs;
|
|
19247
19313
|
} catch {
|
|
19248
19314
|
return null;
|
|
19249
19315
|
}
|
|
@@ -19251,7 +19317,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
19251
19317
|
const resolved = resolveFile(f);
|
|
19252
19318
|
if (!resolved) continue;
|
|
19253
19319
|
try {
|
|
19254
|
-
const stat3 = (0,
|
|
19320
|
+
const stat3 = (0, import_node_fs32.statSync)(resolved);
|
|
19255
19321
|
if (stat3.mtimeMs > debounceTime) {
|
|
19256
19322
|
return null;
|
|
19257
19323
|
}
|
|
@@ -19267,8 +19333,8 @@ function computeContentHash(files) {
|
|
|
19267
19333
|
for (const f of sorted) {
|
|
19268
19334
|
const resolved = resolveFile(f) ?? f;
|
|
19269
19335
|
try {
|
|
19270
|
-
if ((0,
|
|
19271
|
-
hash.update((0,
|
|
19336
|
+
if ((0, import_node_fs32.existsSync)(resolved)) {
|
|
19337
|
+
hash.update((0, import_node_fs32.readFileSync)(resolved));
|
|
19272
19338
|
}
|
|
19273
19339
|
} catch {
|
|
19274
19340
|
}
|
|
@@ -19278,9 +19344,9 @@ function computeContentHash(files) {
|
|
|
19278
19344
|
function checkContentHash(files, sessionId) {
|
|
19279
19345
|
const hash = computeContentHash(files);
|
|
19280
19346
|
const file = scopedFile(HASH_FILE, sessionId);
|
|
19281
|
-
if ((0,
|
|
19347
|
+
if ((0, import_node_fs32.existsSync)(file)) {
|
|
19282
19348
|
try {
|
|
19283
|
-
const storedHash = (0,
|
|
19349
|
+
const storedHash = (0, import_node_fs32.readFileSync)(file, "utf-8").trim();
|
|
19284
19350
|
if (hash === storedHash) {
|
|
19285
19351
|
return { skip: "No source changes since last analysis", hash };
|
|
19286
19352
|
}
|
|
@@ -19290,24 +19356,24 @@ function checkContentHash(files, sessionId) {
|
|
|
19290
19356
|
return { skip: null, hash };
|
|
19291
19357
|
}
|
|
19292
19358
|
function recordAnalysisStart(sessionId) {
|
|
19293
|
-
(0,
|
|
19294
|
-
(0,
|
|
19359
|
+
(0, import_node_fs32.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
19360
|
+
(0, import_node_fs32.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
|
|
19295
19361
|
}
|
|
19296
19362
|
function recordPassHash(hash, sessionId) {
|
|
19297
|
-
(0,
|
|
19363
|
+
(0, import_node_fs32.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
|
|
19298
19364
|
}
|
|
19299
19365
|
function narrowToRecent(files, sessionId) {
|
|
19300
19366
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19301
|
-
if (!(0,
|
|
19367
|
+
if (!(0, import_node_fs32.existsSync)(file)) return files;
|
|
19302
19368
|
let debounceTime;
|
|
19303
19369
|
try {
|
|
19304
|
-
debounceTime = (0,
|
|
19370
|
+
debounceTime = (0, import_node_fs32.statSync)(file).mtimeMs;
|
|
19305
19371
|
} catch {
|
|
19306
19372
|
return files;
|
|
19307
19373
|
}
|
|
19308
19374
|
const recent = files.filter((f) => {
|
|
19309
19375
|
try {
|
|
19310
|
-
return (0,
|
|
19376
|
+
return (0, import_node_fs32.existsSync)(f) && (0, import_node_fs32.statSync)(f).mtimeMs > debounceTime;
|
|
19311
19377
|
} catch {
|
|
19312
19378
|
return false;
|
|
19313
19379
|
}
|
|
@@ -19320,9 +19386,9 @@ function readIteration(currentCommit, _contentHash) {
|
|
|
19320
19386
|
var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
|
|
19321
19387
|
function readBlockState(currentCommit, opts) {
|
|
19322
19388
|
if (opts?.newUserPrompt) return NO_BLOCKS;
|
|
19323
|
-
if (!(0,
|
|
19389
|
+
if (!(0, import_node_fs32.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
|
|
19324
19390
|
try {
|
|
19325
|
-
const stored = (0,
|
|
19391
|
+
const stored = (0, import_node_fs32.readFileSync)(ITERATION_FILE, "utf-8").trim();
|
|
19326
19392
|
const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
|
|
19327
19393
|
if (!parsed) return NO_BLOCKS;
|
|
19328
19394
|
if (parsed.commit !== currentCommit) return NO_BLOCKS;
|
|
@@ -19368,8 +19434,8 @@ function isSameProblem(previous, current) {
|
|
|
19368
19434
|
return current.split(",").some((k) => prev.has(k));
|
|
19369
19435
|
}
|
|
19370
19436
|
function writeBlockState(commit, state) {
|
|
19371
|
-
(0,
|
|
19372
|
-
(0,
|
|
19437
|
+
(0, import_node_fs32.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
19438
|
+
(0, import_node_fs32.writeFileSync)(
|
|
19373
19439
|
ITERATION_FILE,
|
|
19374
19440
|
JSON.stringify({
|
|
19375
19441
|
v: 2,
|
|
@@ -19474,9 +19540,9 @@ function resolveIgnoreState(keys) {
|
|
|
19474
19540
|
}
|
|
19475
19541
|
function readIgnoreState(sessionId) {
|
|
19476
19542
|
const file = stateFile(sessionId);
|
|
19477
|
-
if (!(0,
|
|
19543
|
+
if (!(0, import_node_fs33.existsSync)(file)) return null;
|
|
19478
19544
|
try {
|
|
19479
|
-
const o = JSON.parse((0,
|
|
19545
|
+
const o = JSON.parse((0, import_node_fs33.readFileSync)(file, "utf-8")) ?? {};
|
|
19480
19546
|
const spent = typeof o.spent === "number" ? o.spent : 0;
|
|
19481
19547
|
const raw = o.active;
|
|
19482
19548
|
let active = null;
|
|
@@ -19500,8 +19566,8 @@ function readIgnoreState(sessionId) {
|
|
|
19500
19566
|
}
|
|
19501
19567
|
function writeIgnoreState(state, sessionId) {
|
|
19502
19568
|
try {
|
|
19503
|
-
(0,
|
|
19504
|
-
(0,
|
|
19569
|
+
(0, import_node_fs33.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
19570
|
+
(0, import_node_fs33.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
|
|
19505
19571
|
} catch {
|
|
19506
19572
|
}
|
|
19507
19573
|
}
|
|
@@ -19884,7 +19950,7 @@ function createRun(opts, globals) {
|
|
|
19884
19950
|
}
|
|
19885
19951
|
|
|
19886
19952
|
// src/commands/analyze/index.ts
|
|
19887
|
-
var
|
|
19953
|
+
var import_node_fs46 = require("node:fs");
|
|
19888
19954
|
|
|
19889
19955
|
// src/lib/repo-context.ts
|
|
19890
19956
|
var import_node_child_process10 = require("node:child_process");
|
|
@@ -20395,6 +20461,112 @@ function partitionSites(rgLines, symbols, opts) {
|
|
|
20395
20461
|
while (callers.length + tests.length > MAX_SITES) callers.pop();
|
|
20396
20462
|
return { callers, tests, dropped };
|
|
20397
20463
|
}
|
|
20464
|
+
var MAX_IMPORTERS = 12;
|
|
20465
|
+
var MAX_IMPORTERS_PER_FILE = 2;
|
|
20466
|
+
function moduleKey(path) {
|
|
20467
|
+
return path.replace(/\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/i, "").replace(/\/index$/, "");
|
|
20468
|
+
}
|
|
20469
|
+
function importSpecifier(text) {
|
|
20470
|
+
const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(text);
|
|
20471
|
+
return m?.[1] ?? null;
|
|
20472
|
+
}
|
|
20473
|
+
function resolveSpecifier(fromFile, spec) {
|
|
20474
|
+
if (!spec.startsWith(".")) return null;
|
|
20475
|
+
const dir = fromFile.includes("/") ? fromFile.slice(0, fromFile.lastIndexOf("/")) : "";
|
|
20476
|
+
const out = [];
|
|
20477
|
+
for (const part of (dir ? dir.split("/") : []).concat(spec.split("/"))) {
|
|
20478
|
+
if (part === "" || part === ".") continue;
|
|
20479
|
+
if (part === "..") {
|
|
20480
|
+
if (out.length === 0) return null;
|
|
20481
|
+
out.pop();
|
|
20482
|
+
continue;
|
|
20483
|
+
}
|
|
20484
|
+
out.push(part);
|
|
20485
|
+
}
|
|
20486
|
+
return out.length > 0 ? moduleKey(out.join("/")) : null;
|
|
20487
|
+
}
|
|
20488
|
+
function partitionImporters(rgLines, changedPaths, opts) {
|
|
20489
|
+
const changedByKey = /* @__PURE__ */ new Map();
|
|
20490
|
+
for (const p of changedPaths) changedByKey.set(moduleKey(p), p);
|
|
20491
|
+
const hits = rgLines.map(parseRgLine).filter((h) => h !== null);
|
|
20492
|
+
hits.sort((a, b) => a.file < b.file ? -1 : a.file > b.file ? 1 : a.line - b.line);
|
|
20493
|
+
const perFile = /* @__PURE__ */ new Map();
|
|
20494
|
+
const out = [];
|
|
20495
|
+
for (const h of hits) {
|
|
20496
|
+
if (out.length >= MAX_IMPORTERS) break;
|
|
20497
|
+
if (opts.sentPaths.has(h.file)) continue;
|
|
20498
|
+
if (opts.isExcluded(h.file)) continue;
|
|
20499
|
+
if (!isCodeSiteFile(h.file)) continue;
|
|
20500
|
+
const spec = importSpecifier(h.text);
|
|
20501
|
+
if (!spec) continue;
|
|
20502
|
+
const resolved = resolveSpecifier(h.file, spec);
|
|
20503
|
+
if (!resolved) continue;
|
|
20504
|
+
const changed = changedByKey.get(resolved);
|
|
20505
|
+
if (!changed) continue;
|
|
20506
|
+
const used = perFile.get(h.file) ?? 0;
|
|
20507
|
+
if (used >= MAX_IMPORTERS_PER_FILE) continue;
|
|
20508
|
+
perFile.set(h.file, used + 1);
|
|
20509
|
+
out.push({ file: h.file, line: h.line, text: h.text.trim().slice(0, SITE_TEXT_MAX), symbol: changed });
|
|
20510
|
+
}
|
|
20511
|
+
return out;
|
|
20512
|
+
}
|
|
20513
|
+
function runRg(args, cwd, timeoutMs) {
|
|
20514
|
+
let res = null;
|
|
20515
|
+
for (const inv of rgInvocations()) {
|
|
20516
|
+
res = (0, import_node_child_process10.spawnSync)(inv.cmd, args, {
|
|
20517
|
+
...inv.argv0 ? { argv0: inv.argv0 } : {},
|
|
20518
|
+
cwd,
|
|
20519
|
+
env: ripgrepEnv(),
|
|
20520
|
+
timeout: timeoutMs,
|
|
20521
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
20522
|
+
encoding: "utf8"
|
|
20523
|
+
});
|
|
20524
|
+
if (res.error?.code !== "ENOENT") break;
|
|
20525
|
+
}
|
|
20526
|
+
if (!res || res.error?.code === "ENOENT") {
|
|
20527
|
+
return { ok: false, reason: "no-tool" };
|
|
20528
|
+
}
|
|
20529
|
+
if (res.error) {
|
|
20530
|
+
const code = res.error.code;
|
|
20531
|
+
return { ok: false, reason: code === "ETIMEDOUT" ? "timeout" : "error" };
|
|
20532
|
+
}
|
|
20533
|
+
if (res.signal) return { ok: false, reason: "timeout" };
|
|
20534
|
+
if (res.status !== 0 && res.status !== 1) return { ok: false, reason: "error" };
|
|
20535
|
+
return { ok: true, lines: (res.stdout ?? "").split("\n").map((l) => l.replace(/^\.\//, "")).filter(Boolean) };
|
|
20536
|
+
}
|
|
20537
|
+
function findImporters(input) {
|
|
20538
|
+
const basenames = [
|
|
20539
|
+
...new Set(input.changedPaths.map((p) => moduleKey(p).split("/").pop() ?? "").filter((b) => b.length > 0))
|
|
20540
|
+
].slice(0, MAX_SYMBOLS);
|
|
20541
|
+
if (basenames.length === 0) return [];
|
|
20542
|
+
const res = runRg(
|
|
20543
|
+
[
|
|
20544
|
+
"--no-config",
|
|
20545
|
+
"-n",
|
|
20546
|
+
"-w",
|
|
20547
|
+
"-F",
|
|
20548
|
+
"--no-heading",
|
|
20549
|
+
"--color",
|
|
20550
|
+
"never",
|
|
20551
|
+
"-m",
|
|
20552
|
+
"8",
|
|
20553
|
+
"--max-columns",
|
|
20554
|
+
"300",
|
|
20555
|
+
"--max-columns-preview",
|
|
20556
|
+
...basenames.flatMap((b) => ["-e", b]),
|
|
20557
|
+
"-g",
|
|
20558
|
+
"!**/{dist,build,out,vendor,node_modules,.git,coverage,target,__pycache__}/**",
|
|
20559
|
+
"./"
|
|
20560
|
+
],
|
|
20561
|
+
input.cwd,
|
|
20562
|
+
input.timeoutMs
|
|
20563
|
+
);
|
|
20564
|
+
if (!res.ok) return [];
|
|
20565
|
+
return partitionImporters(res.lines, input.changedPaths, {
|
|
20566
|
+
sentPaths: input.sentPaths,
|
|
20567
|
+
isExcluded: input.isExcluded
|
|
20568
|
+
});
|
|
20569
|
+
}
|
|
20398
20570
|
function buildRepoContext(input) {
|
|
20399
20571
|
const started = Date.now();
|
|
20400
20572
|
let signalsByPath;
|
|
@@ -20429,7 +20601,18 @@ function buildRepoContext(input) {
|
|
|
20429
20601
|
const unsupportedExts = [...unsupported].sort().slice(0, 8);
|
|
20430
20602
|
const audit = unsupportedExts.length > 0 ? { unsupported_exts: unsupportedExts } : {};
|
|
20431
20603
|
const symbols = rankSymbols([...new Set(collected)]);
|
|
20604
|
+
const changedPaths = [.../* @__PURE__ */ new Set([...signalsByPath.keys(), ...input.deltaFiles.map((f) => f.path)])];
|
|
20605
|
+
const importers = findImporters({
|
|
20606
|
+
changedPaths,
|
|
20607
|
+
sentPaths: input.sentPaths,
|
|
20608
|
+
isExcluded: input.isExcluded,
|
|
20609
|
+
cwd: input.cwd ?? process.cwd(),
|
|
20610
|
+
timeoutMs: input.timeoutMs ?? RG_TIMEOUT_MS
|
|
20611
|
+
});
|
|
20432
20612
|
if (symbols.length === 0) {
|
|
20613
|
+
if (importers.length > 0) {
|
|
20614
|
+
return { state: "ok", symbols: [], ...audit, callers: [], tests: [], importers, elapsed_ms: Date.now() - started };
|
|
20615
|
+
}
|
|
20433
20616
|
const everySupportedFileFoundNothing = unsupportedExts.length > 0;
|
|
20434
20617
|
return {
|
|
20435
20618
|
state: "absent",
|
|
@@ -20468,34 +20651,19 @@ function buildRepoContext(input) {
|
|
|
20468
20651
|
"!**/{dist,build,out,vendor,node_modules,.git,coverage,target,__pycache__}/**",
|
|
20469
20652
|
"./"
|
|
20470
20653
|
];
|
|
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 };
|
|
20654
|
+
const res = runRg(args, input.cwd ?? process.cwd(), input.timeoutMs ?? RG_TIMEOUT_MS);
|
|
20655
|
+
if (!res.ok) {
|
|
20656
|
+
if (importers.length > 0) {
|
|
20657
|
+
return { state: "ok", symbols, ...audit, callers: [], tests: [], importers, elapsed_ms: Date.now() - started };
|
|
20658
|
+
}
|
|
20659
|
+
return { state: "absent", reason: res.reason, symbols, ...audit };
|
|
20490
20660
|
}
|
|
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);
|
|
20661
|
+
const lines = res.lines;
|
|
20494
20662
|
const { callers, tests, dropped } = partitionSites(lines, symbols, {
|
|
20495
20663
|
sentPaths: input.sentPaths,
|
|
20496
20664
|
isExcluded: input.isExcluded
|
|
20497
20665
|
});
|
|
20498
|
-
if (callers.length === 0 && tests.length === 0) {
|
|
20666
|
+
if (callers.length === 0 && tests.length === 0 && importers.length === 0) {
|
|
20499
20667
|
return {
|
|
20500
20668
|
state: "absent",
|
|
20501
20669
|
reason: "no-sites",
|
|
@@ -20512,6 +20680,7 @@ function buildRepoContext(input) {
|
|
|
20512
20680
|
...audit,
|
|
20513
20681
|
callers,
|
|
20514
20682
|
tests,
|
|
20683
|
+
...importers.length > 0 ? { importers } : {},
|
|
20515
20684
|
elapsed_ms: Date.now() - started
|
|
20516
20685
|
};
|
|
20517
20686
|
}
|
|
@@ -20579,12 +20748,17 @@ function upgradeToExcerpts(rc, opts) {
|
|
|
20579
20748
|
}
|
|
20580
20749
|
function describeRepoContext(rc) {
|
|
20581
20750
|
if (rc.state !== "ok") {
|
|
20582
|
-
const
|
|
20583
|
-
|
|
20751
|
+
const bits = [
|
|
20752
|
+
rc.symbols?.length ? `searched: ${rc.symbols.join(", ")}` : "",
|
|
20753
|
+
rc.dropped_symbols?.length ? `dropped too-common: ${rc.dropped_symbols.join(", ")}` : "",
|
|
20754
|
+
rc.unsupported_exts?.length ? `no rules for: ${rc.unsupported_exts.join(", ")}` : ""
|
|
20755
|
+
].filter(Boolean);
|
|
20756
|
+
return `absent (${rc.reason ?? "unknown"})${bits.length > 0 ? ` \xB7 ${bits.join(" \xB7 ")}` : ""}`;
|
|
20584
20757
|
}
|
|
20585
20758
|
const parts = [
|
|
20586
20759
|
`${rc.symbols?.length ?? 0} symbol(s) \u2192 ${rc.callers?.length ?? 0} caller(s) \xB7 ${rc.tests?.length ?? 0} test(s)`
|
|
20587
20760
|
];
|
|
20761
|
+
if (rc.importers?.length) parts.push(`${rc.importers.length} importer(s)`);
|
|
20588
20762
|
if (rc.excerpts?.length) parts.push(`${rc.excerpts.length} excerpt(s)`);
|
|
20589
20763
|
if (rc.dropped_symbols?.length) parts.push(`dropped too-common: ${rc.dropped_symbols.join(", ")}`);
|
|
20590
20764
|
if (rc.unsupported_exts?.length) parts.push(`no rules for: ${rc.unsupported_exts.join(", ")}`);
|
|
@@ -20712,10 +20886,10 @@ function installRunEvidence(run2) {
|
|
|
20712
20886
|
}
|
|
20713
20887
|
|
|
20714
20888
|
// src/lib/git-frame.ts
|
|
20715
|
-
var
|
|
20889
|
+
var import_node_fs34 = require("node:fs");
|
|
20716
20890
|
var import_node_os5 = require("node:os");
|
|
20717
|
-
var import_node_path25 = require("node:path");
|
|
20718
20891
|
var import_node_path26 = require("node:path");
|
|
20892
|
+
var import_node_path27 = require("node:path");
|
|
20719
20893
|
|
|
20720
20894
|
// src/lib/hardened-git.ts
|
|
20721
20895
|
var import_node_child_process11 = require("node:child_process");
|
|
@@ -20877,8 +21051,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
20877
21051
|
if (SHELL_DYNAMIC.test(raw) || raw === "-") {
|
|
20878
21052
|
return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
|
|
20879
21053
|
}
|
|
20880
|
-
const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0,
|
|
20881
|
-
dir = (0,
|
|
21054
|
+
const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path27.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
|
|
21055
|
+
dir = (0, import_node_path26.isAbsolute)(expanded) ? expanded : (0, import_node_path26.resolve)(dir, expanded);
|
|
20882
21056
|
}
|
|
20883
21057
|
const seg = segments[segmentIndex];
|
|
20884
21058
|
const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
|
|
@@ -20896,8 +21070,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
20896
21070
|
if (SHELL_DYNAMIC.test(raw)) {
|
|
20897
21071
|
return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
|
|
20898
21072
|
}
|
|
20899
|
-
const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0,
|
|
20900
|
-
dir = (0,
|
|
21073
|
+
const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path27.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
|
|
21074
|
+
dir = (0, import_node_path26.isAbsolute)(expanded) ? expanded : (0, import_node_path26.resolve)(dir, expanded);
|
|
20901
21075
|
}
|
|
20902
21076
|
}
|
|
20903
21077
|
return { dir, named, unresolvable: null };
|
|
@@ -20957,14 +21131,14 @@ function gitAt(dir, args) {
|
|
|
20957
21131
|
}
|
|
20958
21132
|
function realpathOr2(p) {
|
|
20959
21133
|
try {
|
|
20960
|
-
return
|
|
21134
|
+
return import_node_fs34.realpathSync.native(p);
|
|
20961
21135
|
} catch {
|
|
20962
|
-
return (0,
|
|
21136
|
+
return (0, import_node_path26.resolve)(p);
|
|
20963
21137
|
}
|
|
20964
21138
|
}
|
|
20965
21139
|
function resolveFrame(input) {
|
|
20966
21140
|
const found = findMomentSegment(input.command, input.on);
|
|
20967
|
-
const hookDirUsable = !!input.hookCwd && (0,
|
|
21141
|
+
const hookDirUsable = !!input.hookCwd && (0, import_node_fs34.existsSync)(input.hookCwd);
|
|
20968
21142
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
20969
21143
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
20970
21144
|
const refuse = (refusal) => ({
|
|
@@ -20987,7 +21161,7 @@ function resolveFrame(input) {
|
|
|
20987
21161
|
if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
|
|
20988
21162
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
20989
21163
|
if (targetDir !== baseDir) {
|
|
20990
|
-
if (!(0,
|
|
21164
|
+
if (!(0, import_node_fs34.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
|
|
20991
21165
|
dir = targetDir;
|
|
20992
21166
|
}
|
|
20993
21167
|
}
|
|
@@ -20998,7 +21172,7 @@ function resolveFrame(input) {
|
|
|
20998
21172
|
const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
|
|
20999
21173
|
const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
|
|
21000
21174
|
const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
|
|
21001
|
-
const commonDir = commonRaw ? realpathOr2((0,
|
|
21175
|
+
const commonDir = commonRaw ? realpathOr2((0, import_node_path26.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path26.resolve)(dir, commonRaw)) : null;
|
|
21002
21176
|
const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
21003
21177
|
return {
|
|
21004
21178
|
moment: found?.moment ?? null,
|
|
@@ -21173,8 +21347,8 @@ function stagedRange(frame, command) {
|
|
|
21173
21347
|
if (plan.kind === "unpredictable") {
|
|
21174
21348
|
return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
|
|
21175
21349
|
}
|
|
21176
|
-
const mergeHead = frame.gitDir ? (0,
|
|
21177
|
-
if (mergeHead && (0,
|
|
21350
|
+
const mergeHead = frame.gitDir ? (0, import_node_path27.join)(frame.gitDir, "MERGE_HEAD") : null;
|
|
21351
|
+
if (mergeHead && (0, import_node_fs34.existsSync)(mergeHead)) {
|
|
21178
21352
|
const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
|
|
21179
21353
|
const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
|
|
21180
21354
|
const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
|
|
@@ -21308,7 +21482,7 @@ function truthy(v) {
|
|
|
21308
21482
|
}
|
|
21309
21483
|
|
|
21310
21484
|
// src/lib/transcript.ts
|
|
21311
|
-
var
|
|
21485
|
+
var import_node_fs35 = require("node:fs");
|
|
21312
21486
|
var MAX_READ_BYTES = 256 * 1024;
|
|
21313
21487
|
var SMALL_FILE_BYTES = 64 * 1024;
|
|
21314
21488
|
var MAX_FILES_LIST = 20;
|
|
@@ -21335,7 +21509,7 @@ async function extractActionSummary(transcriptPath) {
|
|
|
21335
21509
|
function readTurnLines(transcriptPath) {
|
|
21336
21510
|
let size;
|
|
21337
21511
|
try {
|
|
21338
|
-
size = (0,
|
|
21512
|
+
size = (0, import_node_fs35.statSync)(transcriptPath).size;
|
|
21339
21513
|
} catch {
|
|
21340
21514
|
return null;
|
|
21341
21515
|
}
|
|
@@ -21343,7 +21517,7 @@ function readTurnLines(transcriptPath) {
|
|
|
21343
21517
|
let raw;
|
|
21344
21518
|
let windowed = false;
|
|
21345
21519
|
if (size <= SMALL_FILE_BYTES) {
|
|
21346
|
-
raw = (0,
|
|
21520
|
+
raw = (0, import_node_fs35.readFileSync)(transcriptPath, "utf-8");
|
|
21347
21521
|
} else {
|
|
21348
21522
|
windowed = true;
|
|
21349
21523
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
@@ -21851,7 +22025,7 @@ function channelSilence(input) {
|
|
|
21851
22025
|
// src/lib/cli-version.ts
|
|
21852
22026
|
function cliVersion() {
|
|
21853
22027
|
try {
|
|
21854
|
-
return true ? "0.33.0
|
|
22028
|
+
return true ? "0.33.0" : "dev";
|
|
21855
22029
|
} catch {
|
|
21856
22030
|
return "dev";
|
|
21857
22031
|
}
|
|
@@ -21892,7 +22066,7 @@ async function sendSkipBeacon(ctx, reason) {
|
|
|
21892
22066
|
|
|
21893
22067
|
// src/lib/static-analysis.ts
|
|
21894
22068
|
var import_node_child_process12 = require("node:child_process");
|
|
21895
|
-
var
|
|
22069
|
+
var import_node_fs36 = require("node:fs");
|
|
21896
22070
|
var SEVERITY_ORDER = {
|
|
21897
22071
|
Error: 0,
|
|
21898
22072
|
Critical: 0,
|
|
@@ -21903,12 +22077,10 @@ var SEVERITY_ORDER = {
|
|
|
21903
22077
|
Low: 3
|
|
21904
22078
|
};
|
|
21905
22079
|
function isCodacyAvailable() {
|
|
21906
|
-
|
|
21907
|
-
|
|
21908
|
-
|
|
21909
|
-
|
|
21910
|
-
return false;
|
|
21911
|
-
}
|
|
22080
|
+
return codacyAnalysisPath() !== null;
|
|
22081
|
+
}
|
|
22082
|
+
function codacyAnalysisPath() {
|
|
22083
|
+
return whichSync("codacy-analysis");
|
|
21912
22084
|
}
|
|
21913
22085
|
function buildAnalyzerArgv(files) {
|
|
21914
22086
|
return [
|
|
@@ -21935,18 +22107,29 @@ function withFailure(kind, detail) {
|
|
|
21935
22107
|
summary: { ...EMPTY_RESULT.summary, failure: { kind, detail: detail.slice(0, 300) } }
|
|
21936
22108
|
};
|
|
21937
22109
|
}
|
|
22110
|
+
function runCodacyAnalysisIfAvailable(files) {
|
|
22111
|
+
if (files.length === 0) return EMPTY_RESULT;
|
|
22112
|
+
if (!isCodacyAvailable()) {
|
|
22113
|
+
return withFailure(
|
|
22114
|
+
"analyzer_unavailable",
|
|
22115
|
+
"@codacy/analysis-cli was not found on PATH \u2014 no static analysis ran"
|
|
22116
|
+
);
|
|
22117
|
+
}
|
|
22118
|
+
return runCodacyAnalysis(files);
|
|
22119
|
+
}
|
|
21938
22120
|
function runCodacyAnalysis(files) {
|
|
21939
22121
|
const empty = EMPTY_RESULT;
|
|
21940
22122
|
if (files.length === 0) return empty;
|
|
21941
22123
|
const existingFiles = files.filter((f) => {
|
|
21942
22124
|
try {
|
|
21943
|
-
return (0,
|
|
22125
|
+
return (0, import_node_fs36.existsSync)(f);
|
|
21944
22126
|
} catch {
|
|
21945
22127
|
return false;
|
|
21946
22128
|
}
|
|
21947
22129
|
});
|
|
21948
22130
|
if (existingFiles.length === 0) return empty;
|
|
21949
|
-
const
|
|
22131
|
+
const analyzer = codacyAnalysisPath() ?? "codacy-analysis";
|
|
22132
|
+
const proc = (0, import_node_child_process12.spawnSync)(analyzer, buildAnalyzerArgv(existingFiles), {
|
|
21950
22133
|
encoding: "utf-8",
|
|
21951
22134
|
maxBuffer: 10 * 1024 * 1024
|
|
21952
22135
|
});
|
|
@@ -22114,11 +22297,10 @@ var EMPTY_STATIC = {
|
|
|
22114
22297
|
summary: { total_findings: 0, by_severity: {}, tools_run: [] }
|
|
22115
22298
|
};
|
|
22116
22299
|
function runLocalStatic(analyzable, securityFiles, baseline, skipStatic) {
|
|
22117
|
-
if (skipStatic
|
|
22300
|
+
if (skipStatic) return EMPTY_STATIC;
|
|
22118
22301
|
let scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
22119
22302
|
if (baseline) scannable = scannable.filter((f) => changedSinceBaseline(f, baseline));
|
|
22120
|
-
|
|
22121
|
-
return runCodacyAnalysis(scannable);
|
|
22303
|
+
return runCodacyAnalysisIfAvailable(scannable);
|
|
22122
22304
|
}
|
|
22123
22305
|
function localOnlyAndExit(staticResults) {
|
|
22124
22306
|
printJsonCompact({
|
|
@@ -22209,8 +22391,8 @@ async function scope(run2) {
|
|
|
22209
22391
|
}
|
|
22210
22392
|
|
|
22211
22393
|
// src/lib/specs.ts
|
|
22212
|
-
var
|
|
22213
|
-
var
|
|
22394
|
+
var import_node_fs37 = require("node:fs");
|
|
22395
|
+
var import_node_path28 = require("node:path");
|
|
22214
22396
|
var SPEC_CANDIDATES = [
|
|
22215
22397
|
"CLAUDE.md",
|
|
22216
22398
|
"AGENTS.md",
|
|
@@ -22229,6 +22411,16 @@ var SPEC_CANDIDATES = [
|
|
|
22229
22411
|
var DOC_EXT = /\.(md|mdx|ya?ml|txt|rst|adoc)$/i;
|
|
22230
22412
|
var UNCONSULTED_FILE_BYTES = 10240;
|
|
22231
22413
|
var UNCONSULTED_TOTAL_BYTES = 30720;
|
|
22414
|
+
function readSpecFiles(specsOpt, root) {
|
|
22415
|
+
const out = [];
|
|
22416
|
+
for (const raw of specsOpt.split(",").map((f) => f.trim()).filter(Boolean)) {
|
|
22417
|
+
const candidate = (0, import_node_path28.isAbsolute)(raw) ? (0, import_node_path28.relative)(root, raw) : raw;
|
|
22418
|
+
const content = readFileInside(root, candidate, MAX_EXPLICIT_SPEC_FILE_BYTES);
|
|
22419
|
+
if (content === null) continue;
|
|
22420
|
+
out.push({ path: raw, content });
|
|
22421
|
+
}
|
|
22422
|
+
return out;
|
|
22423
|
+
}
|
|
22232
22424
|
function discoverSpecs(consulted = []) {
|
|
22233
22425
|
const result = [];
|
|
22234
22426
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -22241,7 +22433,7 @@ function discoverSpecs(consulted = []) {
|
|
|
22241
22433
|
const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
|
|
22242
22434
|
if (totalBytes >= totalCap) return false;
|
|
22243
22435
|
if (seen.has(specPath)) return true;
|
|
22244
|
-
if (!(0,
|
|
22436
|
+
if (!(0, import_node_fs37.existsSync)(specPath)) return true;
|
|
22245
22437
|
seen.add(specPath);
|
|
22246
22438
|
const remaining = totalCap - totalBytes;
|
|
22247
22439
|
const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
|
|
@@ -22264,7 +22456,7 @@ function discoverSpecs(consulted = []) {
|
|
|
22264
22456
|
if (!addSpec(candidate)) break;
|
|
22265
22457
|
}
|
|
22266
22458
|
for (const dir of ["spec", "docs"]) {
|
|
22267
|
-
if (!(0,
|
|
22459
|
+
if (!(0, import_node_fs37.existsSync)(dir)) continue;
|
|
22268
22460
|
try {
|
|
22269
22461
|
const mdFiles = findMdFiles(dir, 2).sort();
|
|
22270
22462
|
for (const mdFile of mdFiles) {
|
|
@@ -22279,9 +22471,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
22279
22471
|
if (depth >= maxDepth) return [];
|
|
22280
22472
|
const result = [];
|
|
22281
22473
|
try {
|
|
22282
|
-
const entries = (0,
|
|
22474
|
+
const entries = (0, import_node_fs37.readdirSync)(dir, { withFileTypes: true });
|
|
22283
22475
|
for (const entry of entries) {
|
|
22284
|
-
const fullPath = (0,
|
|
22476
|
+
const fullPath = (0, import_node_path28.join)(dir, entry.name);
|
|
22285
22477
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
22286
22478
|
result.push(fullPath);
|
|
22287
22479
|
} else if (entry.isDirectory() && depth < maxDepth - 1) {
|
|
@@ -22294,25 +22486,25 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
22294
22486
|
}
|
|
22295
22487
|
function discoverPlans() {
|
|
22296
22488
|
const home = process.env.HOME ?? "";
|
|
22297
|
-
const homePlansDir = (0,
|
|
22489
|
+
const homePlansDir = (0, import_node_path28.join)(home, ".claude", "plans");
|
|
22298
22490
|
const sources = [];
|
|
22299
22491
|
if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
|
|
22300
|
-
sources.push({ root: process.cwd(), prefix: (0,
|
|
22492
|
+
sources.push({ root: process.cwd(), prefix: (0, import_node_path28.join)(".claude", "plans") });
|
|
22301
22493
|
}
|
|
22302
|
-
if (home && (0,
|
|
22494
|
+
if (home && (0, import_node_fs37.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
|
|
22303
22495
|
const candidates2 = [];
|
|
22304
22496
|
const seen = /* @__PURE__ */ new Set();
|
|
22305
22497
|
for (const source of sources) {
|
|
22306
22498
|
let names2;
|
|
22307
22499
|
try {
|
|
22308
|
-
names2 = (0,
|
|
22500
|
+
names2 = (0, import_node_fs37.readdirSync)(source.prefix ? (0, import_node_path28.join)(source.root, source.prefix) : source.root);
|
|
22309
22501
|
} catch {
|
|
22310
22502
|
continue;
|
|
22311
22503
|
}
|
|
22312
22504
|
for (const f of names2) {
|
|
22313
22505
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
22314
22506
|
seen.add(f);
|
|
22315
|
-
const relPath = source.prefix ? (0,
|
|
22507
|
+
const relPath = source.prefix ? (0, import_node_path28.join)(source.prefix, f) : f;
|
|
22316
22508
|
const stat3 = statRegularInRoot(source.root, relPath);
|
|
22317
22509
|
if (!stat3.ok) continue;
|
|
22318
22510
|
candidates2.push({ name: f, root: source.root, relPath, mtime: stat3.mtimeMs, size: stat3.size });
|
|
@@ -22330,9 +22522,9 @@ function discoverPlans() {
|
|
|
22330
22522
|
function isRealDirectoryChain(root, parts) {
|
|
22331
22523
|
let current = root;
|
|
22332
22524
|
for (const part of parts) {
|
|
22333
|
-
current = (0,
|
|
22525
|
+
current = (0, import_node_path28.join)(current, part);
|
|
22334
22526
|
try {
|
|
22335
|
-
if (!(0,
|
|
22527
|
+
if (!(0, import_node_fs37.lstatSync)(current).isDirectory()) return false;
|
|
22336
22528
|
} catch {
|
|
22337
22529
|
return false;
|
|
22338
22530
|
}
|
|
@@ -22347,7 +22539,7 @@ function discoverGuardDocs(rangeFiles2) {
|
|
|
22347
22539
|
if (result.length >= MAX_SPEC_FILES) break;
|
|
22348
22540
|
if (!GUARD_DOC_EXT.test(path)) continue;
|
|
22349
22541
|
if (path.startsWith("/") || path.includes("..")) continue;
|
|
22350
|
-
if (!(0,
|
|
22542
|
+
if (!(0, import_node_fs37.existsSync)(path)) continue;
|
|
22351
22543
|
const opened = openRegularInRoot(process.cwd(), path);
|
|
22352
22544
|
if (!opened.ok) continue;
|
|
22353
22545
|
if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
|
|
@@ -22533,8 +22725,8 @@ async function mode(run2) {
|
|
|
22533
22725
|
}
|
|
22534
22726
|
|
|
22535
22727
|
// src/lib/fold.ts
|
|
22536
|
-
var
|
|
22537
|
-
var
|
|
22728
|
+
var import_node_fs38 = require("node:fs");
|
|
22729
|
+
var import_node_path29 = require("node:path");
|
|
22538
22730
|
var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
|
|
22539
22731
|
"user",
|
|
22540
22732
|
"assistant",
|
|
@@ -22671,7 +22863,7 @@ function candidateRoots(repoRoot2) {
|
|
|
22671
22863
|
const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
22672
22864
|
const out = [norm];
|
|
22673
22865
|
try {
|
|
22674
|
-
const real =
|
|
22866
|
+
const real = import_node_fs38.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
22675
22867
|
if (real !== norm) out.push(real);
|
|
22676
22868
|
} catch {
|
|
22677
22869
|
}
|
|
@@ -22759,31 +22951,31 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22759
22951
|
}
|
|
22760
22952
|
};
|
|
22761
22953
|
try {
|
|
22762
|
-
if (!(0,
|
|
22763
|
-
ingest((0,
|
|
22954
|
+
if (!(0, import_node_fs38.existsSync)(transcriptPath)) return result;
|
|
22955
|
+
ingest((0, import_node_fs38.readFileSync)(transcriptPath, "utf8"), "agent");
|
|
22764
22956
|
result.coverage.complete = true;
|
|
22765
22957
|
} catch {
|
|
22766
22958
|
return result;
|
|
22767
22959
|
}
|
|
22768
22960
|
try {
|
|
22769
|
-
const sidecarDir = (0,
|
|
22770
|
-
(0,
|
|
22771
|
-
(0,
|
|
22961
|
+
const sidecarDir = (0, import_node_path29.join)(
|
|
22962
|
+
(0, import_node_path29.dirname)(transcriptPath),
|
|
22963
|
+
(0, import_node_path29.basename)(transcriptPath).replace(/\.jsonl$/, ""),
|
|
22772
22964
|
"subagents"
|
|
22773
22965
|
);
|
|
22774
|
-
if ((0,
|
|
22966
|
+
if ((0, import_node_fs38.existsSync)(sidecarDir)) {
|
|
22775
22967
|
const maxFiles = opts.maxSidecars ?? 200;
|
|
22776
22968
|
const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
|
|
22777
22969
|
const found = [];
|
|
22778
22970
|
const walk2 = (d, depth) => {
|
|
22779
22971
|
if (depth > 4) return;
|
|
22780
|
-
for (const e of (0,
|
|
22781
|
-
const p = (0,
|
|
22972
|
+
for (const e of (0, import_node_fs38.readdirSync)(d, { withFileTypes: true })) {
|
|
22973
|
+
const p = (0, import_node_path29.join)(d, e.name);
|
|
22782
22974
|
if (e.isDirectory()) {
|
|
22783
22975
|
walk2(p, depth + 1);
|
|
22784
22976
|
} else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
|
|
22785
22977
|
try {
|
|
22786
|
-
const st = (0,
|
|
22978
|
+
const st = (0, import_node_fs38.statSync)(p);
|
|
22787
22979
|
found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
|
|
22788
22980
|
} catch {
|
|
22789
22981
|
result.coverage.malformed++;
|
|
@@ -22800,7 +22992,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22800
22992
|
continue;
|
|
22801
22993
|
}
|
|
22802
22994
|
try {
|
|
22803
|
-
ingest((0,
|
|
22995
|
+
ingest((0, import_node_fs38.readFileSync)(f.path, "utf8"), "subagent");
|
|
22804
22996
|
bytes += f.size;
|
|
22805
22997
|
result.coverage.subagentFiles++;
|
|
22806
22998
|
} catch {
|
|
@@ -22835,7 +23027,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22835
23027
|
}
|
|
22836
23028
|
function classifyUnobserved(path) {
|
|
22837
23029
|
try {
|
|
22838
|
-
const st = (0,
|
|
23030
|
+
const st = (0, import_node_fs38.statSync)(path);
|
|
22839
23031
|
if (!st.isFile()) return "unreadable";
|
|
22840
23032
|
} catch {
|
|
22841
23033
|
return "unreadable";
|
|
@@ -23102,14 +23294,12 @@ async function evidence(run2) {
|
|
|
23102
23294
|
authorshipWasObservable
|
|
23103
23295
|
});
|
|
23104
23296
|
const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
|
|
23105
|
-
if (!opts.skipStatic
|
|
23297
|
+
if (!opts.skipStatic) {
|
|
23106
23298
|
let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
23107
23299
|
if (baseline) {
|
|
23108
23300
|
allScannable = allScannable.filter((f) => changedSinceBaseline(f, baseline));
|
|
23109
23301
|
}
|
|
23110
|
-
|
|
23111
|
-
staticResults = runCodacyAnalysis(allScannable);
|
|
23112
|
-
}
|
|
23302
|
+
staticResults = runCodacyAnalysisIfAvailable(allScannable);
|
|
23113
23303
|
}
|
|
23114
23304
|
const deltaSet = baseline ? recentForReview.filter((f) => changedSinceBaseline(f, baseline)) : recentForReview;
|
|
23115
23305
|
codeDelta = collectCodeDelta(deltaSet, {
|
|
@@ -23152,20 +23342,20 @@ async function evidence(run2) {
|
|
|
23152
23342
|
}
|
|
23153
23343
|
|
|
23154
23344
|
// src/lib/cache-cleanup.ts
|
|
23155
|
-
var
|
|
23156
|
-
var
|
|
23345
|
+
var import_node_fs39 = require("node:fs");
|
|
23346
|
+
var import_node_path30 = require("node:path");
|
|
23157
23347
|
var CACHE_TTL_DAYS = 7;
|
|
23158
23348
|
function pruneStaleCache() {
|
|
23159
23349
|
try {
|
|
23160
23350
|
const dir = projectPath(CACHE_DIR);
|
|
23161
23351
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
23162
|
-
for (const entry of (0,
|
|
23352
|
+
for (const entry of (0, import_node_fs39.readdirSync)(dir)) {
|
|
23163
23353
|
if (!entry.startsWith("pending-")) continue;
|
|
23164
|
-
const path = (0,
|
|
23354
|
+
const path = (0, import_node_path30.join)(dir, entry);
|
|
23165
23355
|
try {
|
|
23166
|
-
const stat3 = (0,
|
|
23356
|
+
const stat3 = (0, import_node_fs39.statSync)(path);
|
|
23167
23357
|
if (stat3.mtimeMs < cutoff) {
|
|
23168
|
-
(0,
|
|
23358
|
+
(0, import_node_fs39.unlinkSync)(path);
|
|
23169
23359
|
logEvent("cache_entry_pruned", {
|
|
23170
23360
|
path: entry,
|
|
23171
23361
|
age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
|
|
@@ -23179,7 +23369,7 @@ function pruneStaleCache() {
|
|
|
23179
23369
|
}
|
|
23180
23370
|
|
|
23181
23371
|
// src/lib/context-files.ts
|
|
23182
|
-
var
|
|
23372
|
+
var import_node_fs40 = require("node:fs");
|
|
23183
23373
|
var import_node_os6 = require("node:os");
|
|
23184
23374
|
var MAX_CONTEXT_FILES = 10;
|
|
23185
23375
|
var MAX_CONTEXT_FILE_BYTES = 10240;
|
|
@@ -23237,7 +23427,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
|
|
|
23237
23427
|
continue;
|
|
23238
23428
|
}
|
|
23239
23429
|
try {
|
|
23240
|
-
const content = (0,
|
|
23430
|
+
const content = (0, import_node_fs40.readFileSync)(safePath, "utf8");
|
|
23241
23431
|
const bytes = Buffer.byteLength(content);
|
|
23242
23432
|
if (bytes > MAX_CONTEXT_FILE_BYTES) {
|
|
23243
23433
|
logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
|
|
@@ -23322,14 +23512,15 @@ async function repoContext(run2) {
|
|
|
23322
23512
|
dropped: run2.repoContext.dropped_symbols?.length ?? 0,
|
|
23323
23513
|
callers: run2.repoContext.callers?.length ?? 0,
|
|
23324
23514
|
tests: run2.repoContext.tests?.length ?? 0,
|
|
23515
|
+
importers: run2.repoContext.importers?.length ?? 0,
|
|
23325
23516
|
elapsed_ms: run2.repoContext.elapsed_ms ?? null
|
|
23326
23517
|
});
|
|
23327
23518
|
}
|
|
23328
23519
|
|
|
23329
23520
|
// src/lib/seed-runner.ts
|
|
23330
23521
|
var import_promises15 = require("node:fs/promises");
|
|
23331
|
-
var
|
|
23332
|
-
var
|
|
23522
|
+
var import_node_fs41 = require("node:fs");
|
|
23523
|
+
var import_node_path31 = require("node:path");
|
|
23333
23524
|
var import_yaml4 = __toESM(require_dist());
|
|
23334
23525
|
|
|
23335
23526
|
// src/lib/seed.ts
|
|
@@ -23568,7 +23759,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
|
|
|
23568
23759
|
return fm;
|
|
23569
23760
|
}
|
|
23570
23761
|
async function runSeed(opts) {
|
|
23571
|
-
if (!(0,
|
|
23762
|
+
if (!(0, import_node_fs41.existsSync)(STANDARD_FILE)) {
|
|
23572
23763
|
return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
|
|
23573
23764
|
}
|
|
23574
23765
|
let standardDoc;
|
|
@@ -23580,7 +23771,7 @@ async function runSeed(opts) {
|
|
|
23580
23771
|
}
|
|
23581
23772
|
const knowledgeSpec = standardDoc.knowledge_spec ?? {};
|
|
23582
23773
|
let readmeContent;
|
|
23583
|
-
if ((0,
|
|
23774
|
+
if ((0, import_node_fs41.existsSync)("README.md")) {
|
|
23584
23775
|
try {
|
|
23585
23776
|
readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
|
|
23586
23777
|
} catch {
|
|
@@ -23588,7 +23779,7 @@ async function runSeed(opts) {
|
|
|
23588
23779
|
}
|
|
23589
23780
|
let claudeMdContent;
|
|
23590
23781
|
for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
|
|
23591
|
-
if ((0,
|
|
23782
|
+
if ((0, import_node_fs41.existsSync)(p)) {
|
|
23592
23783
|
try {
|
|
23593
23784
|
claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
|
|
23594
23785
|
break;
|
|
@@ -23611,8 +23802,8 @@ async function runSeed(opts) {
|
|
|
23611
23802
|
if (candidates2.length === 0) {
|
|
23612
23803
|
return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
|
|
23613
23804
|
}
|
|
23614
|
-
const overviewPath = (0,
|
|
23615
|
-
if ((0,
|
|
23805
|
+
const overviewPath = (0, import_node_path31.join)(MEMORY_DIR, "domain", "project-overview.md");
|
|
23806
|
+
if ((0, import_node_fs41.existsSync)(overviewPath) && !opts.force) {
|
|
23616
23807
|
return { created: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
|
|
23617
23808
|
}
|
|
23618
23809
|
if (opts.dryRun) {
|
|
@@ -23654,7 +23845,7 @@ async function runSeed(opts) {
|
|
|
23654
23845
|
continue;
|
|
23655
23846
|
}
|
|
23656
23847
|
try {
|
|
23657
|
-
await (0, import_promises15.mkdir)((0,
|
|
23848
|
+
await (0, import_promises15.mkdir)((0, import_node_path31.dirname)(targetPath), { recursive: true });
|
|
23658
23849
|
await (0, import_promises15.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
|
|
23659
23850
|
created++;
|
|
23660
23851
|
opts.onCreated?.(nodeId, filePathRel, c);
|
|
@@ -23667,8 +23858,8 @@ async function runSeed(opts) {
|
|
|
23667
23858
|
}
|
|
23668
23859
|
|
|
23669
23860
|
// src/commands/analyze/phases/08-memory-manifest.ts
|
|
23670
|
-
var
|
|
23671
|
-
var
|
|
23861
|
+
var import_node_fs42 = require("node:fs");
|
|
23862
|
+
var import_node_path32 = require("node:path");
|
|
23672
23863
|
async function memoryManifest(run2) {
|
|
23673
23864
|
const { globals } = run2;
|
|
23674
23865
|
const { serviceUrl, token } = run2;
|
|
@@ -23678,9 +23869,9 @@ async function memoryManifest(run2) {
|
|
|
23678
23869
|
let autoSeedNotice = null;
|
|
23679
23870
|
try {
|
|
23680
23871
|
await ensureMemoryDir();
|
|
23681
|
-
const seedMarker = (0,
|
|
23682
|
-
const hasStandard = (0,
|
|
23683
|
-
const alreadyTried = (0,
|
|
23872
|
+
const seedMarker = (0, import_node_path32.join)(VERITY_DIR, ".seeded");
|
|
23873
|
+
const hasStandard = (0, import_node_fs42.existsSync)(STANDARD_FILE);
|
|
23874
|
+
const alreadyTried = (0, import_node_fs42.existsSync)(seedMarker);
|
|
23684
23875
|
if (hasStandard && !alreadyTried) {
|
|
23685
23876
|
const preManifest = await buildManifest();
|
|
23686
23877
|
if (preManifest.nodes.length === 0) {
|
|
@@ -23693,7 +23884,7 @@ async function memoryManifest(run2) {
|
|
|
23693
23884
|
dryRun: false
|
|
23694
23885
|
});
|
|
23695
23886
|
if (seedResult.created > 0) {
|
|
23696
|
-
(0,
|
|
23887
|
+
(0, import_node_fs42.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
|
|
23697
23888
|
`);
|
|
23698
23889
|
autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
|
|
23699
23890
|
logEvent("auto_seed_ran", {
|
|
@@ -23701,7 +23892,7 @@ async function memoryManifest(run2) {
|
|
|
23701
23892
|
failed: seedResult.failed
|
|
23702
23893
|
});
|
|
23703
23894
|
} else if (seedResult.skipped === "already_seeded") {
|
|
23704
|
-
(0,
|
|
23895
|
+
(0, import_node_fs42.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
|
|
23705
23896
|
`);
|
|
23706
23897
|
} else {
|
|
23707
23898
|
logEvent("auto_seed_noop", {
|
|
@@ -23796,7 +23987,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
|
|
|
23796
23987
|
}
|
|
23797
23988
|
|
|
23798
23989
|
// src/commands/analyze/phases/10-working-memory.ts
|
|
23799
|
-
var
|
|
23990
|
+
var import_node_path33 = require("node:path");
|
|
23800
23991
|
async function workingMemory(run2) {
|
|
23801
23992
|
const { opts } = run2;
|
|
23802
23993
|
const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run2;
|
|
@@ -23808,7 +23999,7 @@ async function workingMemory(run2) {
|
|
|
23808
23999
|
const priorState = foldForMarks(memorySession.d);
|
|
23809
24000
|
incrementReport = computeIncrement(
|
|
23810
24001
|
allForReview,
|
|
23811
|
-
(p) => fileHash((0,
|
|
24002
|
+
(p) => fileHash((0, import_node_path33.join)(repoRoot(), p)),
|
|
23812
24003
|
priorState.authored_all.map((a) => ({
|
|
23813
24004
|
path: a.path,
|
|
23814
24005
|
hash_at_last_verdict: a.hash_at_last_verdict
|
|
@@ -23890,7 +24081,7 @@ async function workingMemory(run2) {
|
|
|
23890
24081
|
}
|
|
23891
24082
|
|
|
23892
24083
|
// src/lib/note-budget.ts
|
|
23893
|
-
var
|
|
24084
|
+
var import_node_fs43 = require("node:fs");
|
|
23894
24085
|
var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
|
|
23895
24086
|
var EPISODE_STALE_SECONDS = 30 * 60;
|
|
23896
24087
|
var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
|
|
@@ -23912,9 +24103,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
|
|
|
23912
24103
|
}
|
|
23913
24104
|
function readAdvisoryEpisode(sessionId) {
|
|
23914
24105
|
const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
|
|
23915
|
-
if (!(0,
|
|
24106
|
+
if (!(0, import_node_fs43.existsSync)(file)) return null;
|
|
23916
24107
|
try {
|
|
23917
|
-
const o = JSON.parse((0,
|
|
24108
|
+
const o = JSON.parse((0, import_node_fs43.readFileSync)(file, "utf-8")) ?? {};
|
|
23918
24109
|
const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
|
|
23919
24110
|
if (isNaN(delivered)) return null;
|
|
23920
24111
|
return {
|
|
@@ -23928,8 +24119,8 @@ function readAdvisoryEpisode(sessionId) {
|
|
|
23928
24119
|
}
|
|
23929
24120
|
function writeAdvisoryEpisode(episode, sessionId) {
|
|
23930
24121
|
try {
|
|
23931
|
-
(0,
|
|
23932
|
-
(0,
|
|
24122
|
+
(0, import_node_fs43.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
24123
|
+
(0, import_node_fs43.writeFileSync)(
|
|
23933
24124
|
scopedFile(ADVISORY_EPISODE_FILE, sessionId),
|
|
23934
24125
|
JSON.stringify({ v: 1, ...episode })
|
|
23935
24126
|
);
|
|
@@ -24237,14 +24428,14 @@ async function buildRequest(run2) {
|
|
|
24237
24428
|
}
|
|
24238
24429
|
|
|
24239
24430
|
// src/lib/offline.ts
|
|
24240
|
-
var
|
|
24431
|
+
var import_node_fs44 = require("node:fs");
|
|
24241
24432
|
var import_node_crypto11 = require("node:crypto");
|
|
24242
24433
|
function cacheRequest(body) {
|
|
24243
24434
|
try {
|
|
24244
|
-
(0,
|
|
24435
|
+
(0, import_node_fs44.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
24245
24436
|
const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
|
|
24246
24437
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
24247
|
-
(0,
|
|
24438
|
+
(0, import_node_fs44.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
|
|
24248
24439
|
} catch {
|
|
24249
24440
|
}
|
|
24250
24441
|
}
|
|
@@ -24363,8 +24554,8 @@ async function transmit(run2) {
|
|
|
24363
24554
|
}
|
|
24364
24555
|
|
|
24365
24556
|
// src/commands/analyze/phases/13-reconcile.ts
|
|
24366
|
-
var
|
|
24367
|
-
var
|
|
24557
|
+
var import_node_fs45 = require("node:fs");
|
|
24558
|
+
var import_node_path34 = require("node:path");
|
|
24368
24559
|
async function reconcile(run2) {
|
|
24369
24560
|
const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
|
|
24370
24561
|
const sentPaths = codeDelta.files.map((f) => f.path);
|
|
@@ -24393,7 +24584,7 @@ async function reconcile(run2) {
|
|
|
24393
24584
|
const st = foldDossier(memorySession.d);
|
|
24394
24585
|
openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
|
|
24395
24586
|
try {
|
|
24396
|
-
const src = (0,
|
|
24587
|
+
const src = (0, import_node_fs45.readFileSync)((0, import_node_path34.join)(repoRoot(), file), "utf8").split("\n");
|
|
24397
24588
|
const at = src[line - 1];
|
|
24398
24589
|
return at === void 0 ? null : lineSha(at);
|
|
24399
24590
|
} catch {
|
|
@@ -24679,12 +24870,20 @@ async function pullRepoMemory(opts) {
|
|
|
24679
24870
|
let version = null;
|
|
24680
24871
|
let cursor = null;
|
|
24681
24872
|
let pages = 0;
|
|
24682
|
-
const remember = (complete) =>
|
|
24683
|
-
|
|
24684
|
-
|
|
24685
|
-
|
|
24686
|
-
|
|
24687
|
-
|
|
24873
|
+
const remember = async (complete) => {
|
|
24874
|
+
const onDisk = await readPullState();
|
|
24875
|
+
const meanwhile = /* @__PURE__ */ new Map();
|
|
24876
|
+
for (const [path, hash] of onDisk.served) {
|
|
24877
|
+
if (state.served.get(path) !== hash) meanwhile.set(path, hash);
|
|
24878
|
+
}
|
|
24879
|
+
await writePullState({
|
|
24880
|
+
version: complete ? version : null,
|
|
24881
|
+
// A complete pull saw every file the server holds, so its ledger replaces
|
|
24882
|
+
// the old one (a path that stopped arriving was archived) — except for what
|
|
24883
|
+
// another writer recorded while it ran. A partial one only adds.
|
|
24884
|
+
served: complete ? new Map([...served, ...meanwhile]) : new Map([...state.served, ...served, ...meanwhile])
|
|
24885
|
+
});
|
|
24886
|
+
};
|
|
24688
24887
|
do {
|
|
24689
24888
|
const params = new URLSearchParams({ limit: String(PAGE_SIZE) });
|
|
24690
24889
|
if (cursor) params.set("cursor", cursor);
|
|
@@ -24757,7 +24956,7 @@ async function readPullState() {
|
|
|
24757
24956
|
async function writePullState(state) {
|
|
24758
24957
|
try {
|
|
24759
24958
|
await (0, import_promises16.mkdir)(projectPath(VERITY_DIR), { recursive: true });
|
|
24760
|
-
await (
|
|
24959
|
+
await writeFileAtomic(pullStateFile(), JSON.stringify({
|
|
24761
24960
|
...state.version ? { version: state.version } : {},
|
|
24762
24961
|
pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24763
24962
|
served: Object.fromEntries(state.served)
|
|
@@ -25200,7 +25399,7 @@ function registerAnalyzeCommand(program2) {
|
|
|
25200
25399
|
var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
|
|
25201
25400
|
async function runAnalyze(opts, globals) {
|
|
25202
25401
|
if (!verityConfigured()) {
|
|
25203
|
-
(0,
|
|
25402
|
+
(0, import_node_fs46.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
|
|
25204
25403
|
process.exit(0);
|
|
25205
25404
|
}
|
|
25206
25405
|
const run2 = createRun(opts, globals);
|
|
@@ -25221,11 +25420,11 @@ async function runAnalyze(opts, globals) {
|
|
|
25221
25420
|
}
|
|
25222
25421
|
|
|
25223
25422
|
// src/commands/baseline.ts
|
|
25224
|
-
var
|
|
25423
|
+
var import_node_fs48 = require("node:fs");
|
|
25225
25424
|
|
|
25226
25425
|
// src/lib/project-skills.ts
|
|
25227
|
-
var
|
|
25228
|
-
var
|
|
25426
|
+
var import_node_fs47 = require("node:fs");
|
|
25427
|
+
var import_node_path35 = require("node:path");
|
|
25229
25428
|
var PROJECT_SKILL_NAMES = [
|
|
25230
25429
|
"verity-setup",
|
|
25231
25430
|
"verity-analyze",
|
|
@@ -25250,14 +25449,14 @@ var LEGACY_SKILL_NAMES = [
|
|
|
25250
25449
|
var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
|
|
25251
25450
|
function staleProjectSkills() {
|
|
25252
25451
|
const root = projectPath(".claude/skills");
|
|
25253
|
-
if (!(0,
|
|
25254
|
-
return ALL.filter((name) => (0,
|
|
25452
|
+
if (!(0, import_node_fs47.existsSync)(root)) return [];
|
|
25453
|
+
return ALL.filter((name) => (0, import_node_fs47.existsSync)((0, import_node_path35.join)(root, name)));
|
|
25255
25454
|
}
|
|
25256
25455
|
function removeProjectSkills() {
|
|
25257
25456
|
const root = projectPath(".claude/skills");
|
|
25258
25457
|
const removed = [];
|
|
25259
25458
|
for (const name of staleProjectSkills()) {
|
|
25260
|
-
(0,
|
|
25459
|
+
(0, import_node_fs47.rmSync)((0, import_node_path35.join)(root, name), { recursive: true, force: true });
|
|
25261
25460
|
removed.push(name);
|
|
25262
25461
|
}
|
|
25263
25462
|
return removed;
|
|
@@ -25322,13 +25521,13 @@ function registerBaselineCommands(program2) {
|
|
|
25322
25521
|
let memoryMsg = null;
|
|
25323
25522
|
let memoryAgentLine = null;
|
|
25324
25523
|
const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
|
|
25325
|
-
if (realStart && !(0,
|
|
25524
|
+
if (realStart && !(0, import_node_fs48.existsSync)(memoryNotice)) {
|
|
25326
25525
|
const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
|
|
25327
25526
|
if (trackedGraph > 0) {
|
|
25328
25527
|
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
25528
|
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
25529
|
try {
|
|
25331
|
-
(0,
|
|
25530
|
+
(0, import_node_fs48.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
|
|
25332
25531
|
} catch {
|
|
25333
25532
|
}
|
|
25334
25533
|
}
|
|
@@ -25429,7 +25628,7 @@ function hookSource(value) {
|
|
|
25429
25628
|
}
|
|
25430
25629
|
|
|
25431
25630
|
// src/commands/review.ts
|
|
25432
|
-
var
|
|
25631
|
+
var import_node_fs49 = require("node:fs");
|
|
25433
25632
|
function registerReviewCommand(program2) {
|
|
25434
25633
|
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
25634
|
const globals = program2.opts();
|
|
@@ -25446,45 +25645,22 @@ async function runReview(opts, globals) {
|
|
|
25446
25645
|
const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
|
|
25447
25646
|
const analyzable = filterAnalyzable(allFiles);
|
|
25448
25647
|
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
|
-
}
|
|
25648
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs49.existsSync)(f) || resolveFile(f) !== null);
|
|
25649
|
+
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
25460
25650
|
const codeDelta = collectCodeDelta(allFiles);
|
|
25461
25651
|
const tokenResult = await resolveToken(globals.token);
|
|
25462
25652
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
25463
25653
|
if (!tokenResult.ok || !urlResult.ok) {
|
|
25654
|
+
const staticFailure = staticResults.summary.failure;
|
|
25464
25655
|
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.",
|
|
25656
|
+
gate_decision: "WARN",
|
|
25657
|
+
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
25658
|
unauthenticated: true,
|
|
25468
25659
|
static_results: staticResults
|
|
25469
25660
|
});
|
|
25470
25661
|
process.exit(0);
|
|
25471
25662
|
}
|
|
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
|
-
}
|
|
25663
|
+
const specs = opts.specs ? readSpecFiles(opts.specs, repoRoot()) : discoverSpecs();
|
|
25488
25664
|
const plans = discoverPlans();
|
|
25489
25665
|
const requestBody = {
|
|
25490
25666
|
static_results: staticResults,
|
|
@@ -25517,9 +25693,10 @@ async function runReview(opts, globals) {
|
|
|
25517
25693
|
});
|
|
25518
25694
|
if (!result.ok) {
|
|
25519
25695
|
printError(`Service error: ${result.error}`);
|
|
25696
|
+
const staticFailure = staticResults.summary.failure;
|
|
25520
25697
|
printJsonCompact({
|
|
25521
|
-
gate_decision: "
|
|
25522
|
-
systemMessage: "Verity:
|
|
25698
|
+
gate_decision: "WARN",
|
|
25699
|
+
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
25700
|
offline: true,
|
|
25524
25701
|
static_results: staticResults
|
|
25525
25702
|
});
|
|
@@ -25534,8 +25711,8 @@ async function runReview(opts, globals) {
|
|
|
25534
25711
|
}
|
|
25535
25712
|
|
|
25536
25713
|
// src/commands/guard.ts
|
|
25537
|
-
var
|
|
25538
|
-
var
|
|
25714
|
+
var import_node_fs50 = require("node:fs");
|
|
25715
|
+
var import_node_path36 = require("node:path");
|
|
25539
25716
|
|
|
25540
25717
|
// src/lib/terminal-text.ts
|
|
25541
25718
|
var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
|
|
@@ -25910,7 +26087,7 @@ async function buildAgentDiffs(ctx, paths, limits = { perFileChars: 24e3, totalC
|
|
|
25910
26087
|
// src/commands/guard.ts
|
|
25911
26088
|
var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
25912
26089
|
var GUARD_BLOCK_CAP = 2;
|
|
25913
|
-
var GUARD_ITER_FILE = (0,
|
|
26090
|
+
var GUARD_ITER_FILE = (0, import_node_path36.join)(VERITY_DIR, ".guard-iteration");
|
|
25914
26091
|
function readPreToolUseStdin() {
|
|
25915
26092
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
25916
26093
|
return new Promise((resolve6) => {
|
|
@@ -25955,7 +26132,7 @@ function readPreToolUseStdin() {
|
|
|
25955
26132
|
}
|
|
25956
26133
|
function readIterMap() {
|
|
25957
26134
|
try {
|
|
25958
|
-
const raw = JSON.parse((0,
|
|
26135
|
+
const raw = JSON.parse((0, import_node_fs50.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
25959
26136
|
if (raw && typeof raw === "object") {
|
|
25960
26137
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
25961
26138
|
return { [raw.moment]: raw.count };
|
|
@@ -25975,10 +26152,10 @@ function readIter(moment) {
|
|
|
25975
26152
|
}
|
|
25976
26153
|
function writeIter(moment, count) {
|
|
25977
26154
|
try {
|
|
25978
|
-
(0,
|
|
26155
|
+
(0, import_node_fs50.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
25979
26156
|
const map = readIterMap();
|
|
25980
26157
|
map[moment] = count;
|
|
25981
|
-
(0,
|
|
26158
|
+
(0, import_node_fs50.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
25982
26159
|
} catch {
|
|
25983
26160
|
}
|
|
25984
26161
|
}
|
|
@@ -25988,10 +26165,10 @@ function resetIter(moment) {
|
|
|
25988
26165
|
if (!(moment in map)) return;
|
|
25989
26166
|
delete map[moment];
|
|
25990
26167
|
if (Object.keys(map).length === 0) {
|
|
25991
|
-
if ((0,
|
|
26168
|
+
if ((0, import_node_fs50.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs50.unlinkSync)(GUARD_ITER_FILE);
|
|
25992
26169
|
} else {
|
|
25993
|
-
(0,
|
|
25994
|
-
(0,
|
|
26170
|
+
(0, import_node_fs50.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
26171
|
+
(0, import_node_fs50.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
25995
26172
|
}
|
|
25996
26173
|
} catch {
|
|
25997
26174
|
}
|
|
@@ -26061,13 +26238,8 @@ function hasBlockingFinding(response, sentFiles) {
|
|
|
26061
26238
|
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
26062
26239
|
const analyzable = filterAnalyzable(files);
|
|
26063
26240
|
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
|
-
}
|
|
26241
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs50.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
26242
|
+
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
26071
26243
|
const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
|
|
26072
26244
|
const requestBody = {
|
|
26073
26245
|
static_results: staticResults,
|
|
@@ -26143,6 +26315,9 @@ function worstGate(...gates) {
|
|
|
26143
26315
|
};
|
|
26144
26316
|
return GATES[Math.max(...gates.map(rank2))];
|
|
26145
26317
|
}
|
|
26318
|
+
function oneShotLostOutcome(input) {
|
|
26319
|
+
return input.agentGate === "FAIL" && input.agentBlocking ? "block" : "allow-without-review";
|
|
26320
|
+
}
|
|
26146
26321
|
function withAgentVerdict(oneShot, agent) {
|
|
26147
26322
|
if (agent.one_shot_source === "none" && typeof oneShot.gate_decision === "string") {
|
|
26148
26323
|
const added = agent.findings.filter((f) => f.agent_added === true);
|
|
@@ -26311,6 +26486,7 @@ async function runGuard(opts, globals) {
|
|
|
26311
26486
|
symbols: repoContext2.symbols?.length ?? 0,
|
|
26312
26487
|
callers: repoContext2.callers?.length ?? 0,
|
|
26313
26488
|
tests: repoContext2.tests?.length ?? 0,
|
|
26489
|
+
importers: repoContext2.importers?.length ?? 0,
|
|
26314
26490
|
excerpts: repoContext2.excerpts?.length ?? 0,
|
|
26315
26491
|
elapsed_ms: repoContext2.elapsed_ms ?? null
|
|
26316
26492
|
});
|
|
@@ -26357,13 +26533,6 @@ async function runGuard(opts, globals) {
|
|
|
26357
26533
|
const agentOutcome = agent ? await agent : null;
|
|
26358
26534
|
const agentVerdict = agentOutcome?.kind === "finished" && agentOutcome.response.gate_decision ? agentOutcome.response : null;
|
|
26359
26535
|
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
26536
|
const oneShotResponse = result.ok ? result.data : {};
|
|
26368
26537
|
const response = agentVerdict ? withAgentVerdict(oneShotResponse, agentVerdict) : oneShotResponse;
|
|
26369
26538
|
if (opts.json) process.stderr.write(JSON.stringify(response) + "\n");
|
|
@@ -26375,6 +26544,19 @@ async function runGuard(opts, globals) {
|
|
|
26375
26544
|
const covDetail = agentLine ? `${coverageBlock(coverage)}
|
|
26376
26545
|
${agentLine}` : coverageBlock(coverage);
|
|
26377
26546
|
const witnessed = [...codeDelta.files.map((f) => f.path), ...agentVerdict?.witnessed_files ?? []];
|
|
26547
|
+
if (!result.ok) {
|
|
26548
|
+
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." : "";
|
|
26549
|
+
if (oneShotLostOutcome({ agentGate: decision, agentBlocking: hasBlockingFinding(response, witnessed) }) === "block") {
|
|
26550
|
+
writeIter(moment, iter + 1);
|
|
26551
|
+
writeBlockMessage(moment, response, covDetail);
|
|
26552
|
+
process.exit(2);
|
|
26553
|
+
}
|
|
26554
|
+
const agentNote = agentLine ? ` ${agentLine}, but it reviewed only part of the change.` : "";
|
|
26555
|
+
emitAllowNotice(
|
|
26556
|
+
`\u26A0 Verity ${moment}: ${authRemedy ? "not authorized" : "no single-pass review"} \u2014 ${verb}ed WITHOUT review${authRemedy}`,
|
|
26557
|
+
`Verity ${moment}: the single-pass review did not come back (${result.error}); the ${verb} was allowed WITHOUT a Verity review.${agentNote}${authRemedy}`
|
|
26558
|
+
);
|
|
26559
|
+
}
|
|
26378
26560
|
if (decision === "FAIL" && hasBlockingFinding(response, witnessed)) {
|
|
26379
26561
|
writeIter(moment, iter + 1);
|
|
26380
26562
|
writeBlockMessage(moment, response, covDetail);
|
|
@@ -26566,7 +26748,7 @@ function registerIgnoreCommand(program2) {
|
|
|
26566
26748
|
|
|
26567
26749
|
// src/commands/waive.ts
|
|
26568
26750
|
var import_node_crypto12 = require("node:crypto");
|
|
26569
|
-
var
|
|
26751
|
+
var import_node_fs51 = require("node:fs");
|
|
26570
26752
|
function registerWaiveCommand(program2) {
|
|
26571
26753
|
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
26754
|
const globals = program2.opts();
|
|
@@ -26595,7 +26777,7 @@ function registerWaiveCommand(program2) {
|
|
|
26595
26777
|
if (opts.file) {
|
|
26596
26778
|
body.file = opts.file;
|
|
26597
26779
|
try {
|
|
26598
|
-
body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0,
|
|
26780
|
+
body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs51.readFileSync)(opts.file)).digest("hex");
|
|
26599
26781
|
} catch {
|
|
26600
26782
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
26601
26783
|
process.exit(1);
|
|
@@ -26620,10 +26802,10 @@ function registerWaiveCommand(program2) {
|
|
|
26620
26802
|
}
|
|
26621
26803
|
|
|
26622
26804
|
// src/commands/init.ts
|
|
26623
|
-
var
|
|
26805
|
+
var import_node_fs55 = require("node:fs");
|
|
26624
26806
|
var import_promises19 = require("node:fs/promises");
|
|
26625
26807
|
var import_yaml6 = __toESM(require_dist());
|
|
26626
|
-
var
|
|
26808
|
+
var import_node_path39 = require("node:path");
|
|
26627
26809
|
var import_node_child_process17 = require("node:child_process");
|
|
26628
26810
|
|
|
26629
26811
|
// src/lib/banner.ts
|
|
@@ -26702,18 +26884,13 @@ function printPhase(n, of, title, subtitle) {
|
|
|
26702
26884
|
}
|
|
26703
26885
|
|
|
26704
26886
|
// src/commands/doctor.ts
|
|
26705
|
-
var
|
|
26887
|
+
var import_node_fs52 = require("node:fs");
|
|
26706
26888
|
|
|
26707
26889
|
// src/lib/prereqs.ts
|
|
26708
26890
|
var import_node_child_process15 = require("node:child_process");
|
|
26709
26891
|
var MIN_NODE_MAJOR = 20;
|
|
26710
26892
|
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
|
-
}
|
|
26893
|
+
return whichSync(bin, { real: false });
|
|
26717
26894
|
}
|
|
26718
26895
|
function checkNode() {
|
|
26719
26896
|
const version = process.version;
|
|
@@ -26914,11 +27091,11 @@ async function buildReport() {
|
|
|
26914
27091
|
const wiring = await resolveHookWiring();
|
|
26915
27092
|
const hooks = wiring.status;
|
|
26916
27093
|
const telemetry = await checkTelemetry();
|
|
26917
|
-
const hasConfig = (0,
|
|
27094
|
+
const hasConfig = (0, import_node_fs52.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
26918
27095
|
const artifacts = {
|
|
26919
|
-
standard: (0,
|
|
27096
|
+
standard: (0, import_node_fs52.existsSync)(projectPath(STANDARD_FILE)),
|
|
26920
27097
|
analysisConfig: hasConfig,
|
|
26921
|
-
verityMd: (0,
|
|
27098
|
+
verityMd: (0, import_node_fs52.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
26922
27099
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
26923
27100
|
};
|
|
26924
27101
|
const next = [];
|
|
@@ -27049,8 +27226,8 @@ function registerDoctorCommand(program2) {
|
|
|
27049
27226
|
}
|
|
27050
27227
|
|
|
27051
27228
|
// src/commands/migrate.ts
|
|
27052
|
-
var
|
|
27053
|
-
var
|
|
27229
|
+
var import_node_fs53 = require("node:fs");
|
|
27230
|
+
var import_node_path37 = require("node:path");
|
|
27054
27231
|
var import_node_child_process16 = require("node:child_process");
|
|
27055
27232
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
27056
27233
|
function defaultNpmRemover(pkg) {
|
|
@@ -27087,12 +27264,12 @@ async function runMigration(opts = {}) {
|
|
|
27087
27264
|
return { actions, migrated: actions.length > 0 };
|
|
27088
27265
|
}
|
|
27089
27266
|
function migrateProjectDir(root, actions) {
|
|
27090
|
-
const gateDir = (0,
|
|
27091
|
-
const verityDir = (0,
|
|
27092
|
-
if ((0,
|
|
27267
|
+
const gateDir = (0, import_node_path37.join)(root, ".gate");
|
|
27268
|
+
const verityDir = (0, import_node_path37.join)(root, ".verity");
|
|
27269
|
+
if ((0, import_node_fs53.existsSync)(gateDir) && !(0, import_node_fs53.existsSync)(verityDir)) {
|
|
27093
27270
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
27094
27271
|
}
|
|
27095
|
-
if ((0,
|
|
27272
|
+
if ((0, import_node_fs53.existsSync)(gateDir) && (0, import_node_fs53.existsSync)(verityDir)) {
|
|
27096
27273
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
27097
27274
|
}
|
|
27098
27275
|
return false;
|
|
@@ -27113,13 +27290,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
27113
27290
|
}
|
|
27114
27291
|
}
|
|
27115
27292
|
if (moved) {
|
|
27116
|
-
if ((0,
|
|
27293
|
+
if ((0, import_node_fs53.existsSync)(gateDir)) {
|
|
27117
27294
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
27118
27295
|
if (carried > 0) {
|
|
27119
27296
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
27120
27297
|
}
|
|
27121
27298
|
try {
|
|
27122
|
-
(0,
|
|
27299
|
+
(0, import_node_fs53.rmSync)(gateDir, { recursive: true, force: true });
|
|
27123
27300
|
} catch {
|
|
27124
27301
|
}
|
|
27125
27302
|
}
|
|
@@ -27135,18 +27312,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
27135
27312
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
27136
27313
|
}
|
|
27137
27314
|
try {
|
|
27138
|
-
(0,
|
|
27315
|
+
(0, import_node_fs53.rmSync)(gateDir, { recursive: true, force: true });
|
|
27139
27316
|
} catch {
|
|
27140
27317
|
}
|
|
27141
27318
|
return carried > 0;
|
|
27142
27319
|
}
|
|
27143
27320
|
function migrateGlobalCredentials(home, actions) {
|
|
27144
27321
|
if (!home) return;
|
|
27145
|
-
const gateCreds = (0,
|
|
27146
|
-
const verityCreds = (0,
|
|
27147
|
-
if (!(0,
|
|
27148
|
-
if (!(0,
|
|
27149
|
-
(0,
|
|
27322
|
+
const gateCreds = (0, import_node_path37.join)(home, ".gate", "credentials");
|
|
27323
|
+
const verityCreds = (0, import_node_path37.join)(home, ".verity", "credentials");
|
|
27324
|
+
if (!(0, import_node_fs53.existsSync)(gateCreds)) return;
|
|
27325
|
+
if (!(0, import_node_fs53.existsSync)(verityCreds)) {
|
|
27326
|
+
(0, import_node_fs53.mkdirSync)((0, import_node_path37.join)(home, ".verity"), { recursive: true });
|
|
27150
27327
|
moveFile(gateCreds, verityCreds);
|
|
27151
27328
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
27152
27329
|
return;
|
|
@@ -27168,8 +27345,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
27168
27345
|
}
|
|
27169
27346
|
}
|
|
27170
27347
|
async function migrateClaudeMd(root, actions) {
|
|
27171
|
-
const claudeMd = (0,
|
|
27172
|
-
const hadLegacyBlock = (0,
|
|
27348
|
+
const claudeMd = (0, import_node_path37.join)(root, "CLAUDE.md");
|
|
27349
|
+
const hadLegacyBlock = (0, import_node_fs53.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
27173
27350
|
if (!hadLegacyBlock) return;
|
|
27174
27351
|
try {
|
|
27175
27352
|
await ensureClaudeMdPointer(root);
|
|
@@ -27179,9 +27356,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
27179
27356
|
}
|
|
27180
27357
|
}
|
|
27181
27358
|
function migrateStandardFile(root, actions) {
|
|
27182
|
-
const gateMd = (0,
|
|
27183
|
-
const verityMd = (0,
|
|
27184
|
-
if (!(0,
|
|
27359
|
+
const gateMd = (0, import_node_path37.join)(root, "GATE.md");
|
|
27360
|
+
const verityMd = (0, import_node_path37.join)(root, "VERITY.md");
|
|
27361
|
+
if (!(0, import_node_fs53.existsSync)(gateMd) || (0, import_node_fs53.existsSync)(verityMd)) return;
|
|
27185
27362
|
let moved = false;
|
|
27186
27363
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
27187
27364
|
try {
|
|
@@ -27193,12 +27370,12 @@ function migrateStandardFile(root, actions) {
|
|
|
27193
27370
|
if (!moved) moveFile(gateMd, verityMd);
|
|
27194
27371
|
const content = readFileSyncSafe(verityMd);
|
|
27195
27372
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
27196
|
-
if (refreshed !== content) (0,
|
|
27373
|
+
if (refreshed !== content) (0, import_node_fs53.writeFileSync)(verityMd, refreshed);
|
|
27197
27374
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
27198
27375
|
}
|
|
27199
27376
|
async function migrateTelemetryHeaders(root, actions) {
|
|
27200
|
-
const file = (0,
|
|
27201
|
-
if (!(0,
|
|
27377
|
+
const file = (0, import_node_path37.join)(root, ".claude", "settings.local.json");
|
|
27378
|
+
if (!(0, import_node_fs53.existsSync)(file)) return;
|
|
27202
27379
|
let settings;
|
|
27203
27380
|
try {
|
|
27204
27381
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -27246,14 +27423,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
27246
27423
|
}
|
|
27247
27424
|
if (toAppend.length > 0) {
|
|
27248
27425
|
const sep4 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
27249
|
-
(0,
|
|
27426
|
+
(0, import_node_fs53.writeFileSync)(verityCreds, verityContent + sep4 + toAppend.join("\n") + "\n");
|
|
27250
27427
|
}
|
|
27251
|
-
(0,
|
|
27428
|
+
(0, import_node_fs53.rmSync)(gateCreds, { force: true });
|
|
27252
27429
|
return toAppend.length;
|
|
27253
27430
|
}
|
|
27254
27431
|
function readFileSyncSafe(path) {
|
|
27255
27432
|
try {
|
|
27256
|
-
return (0,
|
|
27433
|
+
return (0, import_node_fs53.readFileSync)(path, "utf-8");
|
|
27257
27434
|
} catch {
|
|
27258
27435
|
return "";
|
|
27259
27436
|
}
|
|
@@ -27268,35 +27445,35 @@ function hasStagedChanges(root) {
|
|
|
27268
27445
|
}
|
|
27269
27446
|
function moveDir(from, to) {
|
|
27270
27447
|
try {
|
|
27271
|
-
(0,
|
|
27448
|
+
(0, import_node_fs53.renameSync)(from, to);
|
|
27272
27449
|
} catch (err) {
|
|
27273
27450
|
if (err.code !== "EXDEV") throw err;
|
|
27274
|
-
(0,
|
|
27275
|
-
(0,
|
|
27451
|
+
(0, import_node_fs53.cpSync)(from, to, { recursive: true });
|
|
27452
|
+
(0, import_node_fs53.rmSync)(from, { recursive: true, force: true });
|
|
27276
27453
|
}
|
|
27277
27454
|
}
|
|
27278
27455
|
function moveFile(from, to) {
|
|
27279
27456
|
try {
|
|
27280
|
-
(0,
|
|
27457
|
+
(0, import_node_fs53.renameSync)(from, to);
|
|
27281
27458
|
} catch (err) {
|
|
27282
27459
|
if (err.code !== "EXDEV") throw err;
|
|
27283
|
-
(0,
|
|
27284
|
-
(0,
|
|
27460
|
+
(0, import_node_fs53.cpSync)(from, to);
|
|
27461
|
+
(0, import_node_fs53.rmSync)(from, { force: true });
|
|
27285
27462
|
}
|
|
27286
27463
|
}
|
|
27287
27464
|
function carryLegacyContents(gateDir, verityDir) {
|
|
27288
27465
|
let copied = 0;
|
|
27289
27466
|
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,
|
|
27467
|
+
const srcDir = (0, import_node_path37.join)(gateDir, relDir);
|
|
27468
|
+
for (const entry of (0, import_node_fs53.readdirSync)(srcDir)) {
|
|
27469
|
+
const rel = relDir ? (0, import_node_path37.join)(relDir, entry) : entry;
|
|
27470
|
+
const src = (0, import_node_path37.join)(gateDir, rel);
|
|
27471
|
+
const dest = (0, import_node_path37.join)(verityDir, rel);
|
|
27472
|
+
if ((0, import_node_fs53.statSync)(src).isDirectory()) {
|
|
27296
27473
|
walk2(rel);
|
|
27297
|
-
} else if (!(0,
|
|
27298
|
-
(0,
|
|
27299
|
-
(0,
|
|
27474
|
+
} else if (!(0, import_node_fs53.existsSync)(dest)) {
|
|
27475
|
+
(0, import_node_fs53.mkdirSync)((0, import_node_path37.dirname)(dest), { recursive: true });
|
|
27476
|
+
(0, import_node_fs53.cpSync)(src, dest);
|
|
27300
27477
|
copied++;
|
|
27301
27478
|
}
|
|
27302
27479
|
}
|
|
@@ -27305,22 +27482,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
27305
27482
|
return copied;
|
|
27306
27483
|
}
|
|
27307
27484
|
async function needsMigration(root = repoRoot()) {
|
|
27308
|
-
const gateDir = (0,
|
|
27309
|
-
const verityDir = (0,
|
|
27310
|
-
if ((0,
|
|
27311
|
-
if ((0,
|
|
27312
|
-
if ((0,
|
|
27485
|
+
const gateDir = (0, import_node_path37.join)(root, ".gate");
|
|
27486
|
+
const verityDir = (0, import_node_path37.join)(root, ".verity");
|
|
27487
|
+
if ((0, import_node_fs53.existsSync)(gateDir) && !(0, import_node_fs53.existsSync)(verityDir)) return true;
|
|
27488
|
+
if ((0, import_node_fs53.existsSync)(gateDir) && (0, import_node_fs53.existsSync)(verityDir)) {
|
|
27489
|
+
if ((0, import_node_fs53.existsSync)((0, import_node_path37.join)(gateDir, "credentials")) && !(0, import_node_fs53.existsSync)((0, import_node_path37.join)(verityDir, "credentials"))) {
|
|
27313
27490
|
return true;
|
|
27314
27491
|
}
|
|
27315
|
-
if ((0,
|
|
27492
|
+
if ((0, import_node_fs53.existsSync)((0, import_node_path37.join)(gateDir, "memory")) && !(0, import_node_fs53.existsSync)((0, import_node_path37.join)(verityDir, "memory"))) {
|
|
27316
27493
|
return true;
|
|
27317
27494
|
}
|
|
27318
27495
|
}
|
|
27319
|
-
const claudeMd = (0,
|
|
27320
|
-
if ((0,
|
|
27496
|
+
const claudeMd = (0, import_node_path37.join)(root, "CLAUDE.md");
|
|
27497
|
+
if ((0, import_node_fs53.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
27321
27498
|
return true;
|
|
27322
27499
|
}
|
|
27323
|
-
if ((0,
|
|
27500
|
+
if ((0, import_node_fs53.existsSync)((0, import_node_path37.join)(root, "GATE.md")) && !(0, import_node_fs53.existsSync)((0, import_node_path37.join)(root, "VERITY.md"))) {
|
|
27324
27501
|
return true;
|
|
27325
27502
|
}
|
|
27326
27503
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -27601,9 +27778,9 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
27601
27778
|
}
|
|
27602
27779
|
|
|
27603
27780
|
// src/lib/remote-config.ts
|
|
27604
|
-
var
|
|
27781
|
+
var import_node_fs54 = require("node:fs");
|
|
27605
27782
|
var import_promises18 = require("node:fs/promises");
|
|
27606
|
-
var
|
|
27783
|
+
var import_node_path38 = require("node:path");
|
|
27607
27784
|
var import_yaml5 = __toESM(require_dist());
|
|
27608
27785
|
var IGNORE_RIDER = "verityignore";
|
|
27609
27786
|
async function fetchRemoteSetup(opts) {
|
|
@@ -27648,7 +27825,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
27648
27825
|
written.push(STANDARD_FILE);
|
|
27649
27826
|
if (rider !== null) {
|
|
27650
27827
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
27651
|
-
if (!(0,
|
|
27828
|
+
if (!(0, import_node_fs54.existsSync)(localIgnore)) {
|
|
27652
27829
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
27653
27830
|
written.push(VERITYIGNORE_FILE);
|
|
27654
27831
|
} else {
|
|
@@ -27679,9 +27856,9 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
27679
27856
|
written.push(VERITY_MD_FILE);
|
|
27680
27857
|
return { written, notes };
|
|
27681
27858
|
}
|
|
27682
|
-
async function writeOut(
|
|
27683
|
-
const target = projectPath(
|
|
27684
|
-
await (0, import_promises18.mkdir)((0,
|
|
27859
|
+
async function writeOut(relative3, body) {
|
|
27860
|
+
const target = projectPath(relative3);
|
|
27861
|
+
await (0, import_promises18.mkdir)((0, import_node_path38.dirname)(target), { recursive: true });
|
|
27685
27862
|
await (0, import_promises18.writeFile)(target, body);
|
|
27686
27863
|
}
|
|
27687
27864
|
function describeRemote(found) {
|
|
@@ -27798,15 +27975,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
27798
27975
|
}
|
|
27799
27976
|
function resolveDataDir2() {
|
|
27800
27977
|
const candidates2 = [
|
|
27801
|
-
(0,
|
|
27978
|
+
(0, import_node_path39.join)(__dirname, "..", "data"),
|
|
27802
27979
|
// installed: node_modules/@codacy/verity-cli/data
|
|
27803
|
-
(0,
|
|
27980
|
+
(0, import_node_path39.join)(__dirname, "..", "..", "data"),
|
|
27804
27981
|
// edge case: nested resolution
|
|
27805
|
-
(0,
|
|
27982
|
+
(0, import_node_path39.join)(process.cwd(), "cli", "data")
|
|
27806
27983
|
// local dev: running from repo root
|
|
27807
27984
|
];
|
|
27808
27985
|
for (const candidate of candidates2) {
|
|
27809
|
-
if ((0,
|
|
27986
|
+
if ((0, import_node_fs55.existsSync)((0, import_node_path39.join)(candidate, "skills"))) {
|
|
27810
27987
|
return candidate;
|
|
27811
27988
|
}
|
|
27812
27989
|
}
|
|
@@ -27822,9 +27999,9 @@ async function skillIsCurrent(src, dest) {
|
|
|
27822
27999
|
const list2 = (dir) => {
|
|
27823
28000
|
const out = [];
|
|
27824
28001
|
const walk2 = (d, prefix) => {
|
|
27825
|
-
for (const e of (0,
|
|
28002
|
+
for (const e of (0, import_node_fs55.readdirSync)(d, { withFileTypes: true })) {
|
|
27826
28003
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
27827
|
-
if (e.isDirectory()) walk2((0,
|
|
28004
|
+
if (e.isDirectory()) walk2((0, import_node_path39.join)(d, e.name), rel);
|
|
27828
28005
|
else if (e.isFile()) out.push(rel);
|
|
27829
28006
|
}
|
|
27830
28007
|
};
|
|
@@ -27835,8 +28012,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
27835
28012
|
const shipped = list2(src);
|
|
27836
28013
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
27837
28014
|
for (const rel of shipped) {
|
|
27838
|
-
const a = await (0, import_promises19.readFile)((0,
|
|
27839
|
-
const b = await (0, import_promises19.readFile)((0,
|
|
28015
|
+
const a = await (0, import_promises19.readFile)((0, import_node_path39.join)(src, rel), "utf-8");
|
|
28016
|
+
const b = await (0, import_promises19.readFile)((0, import_node_path39.join)(dest, rel), "utf-8");
|
|
27840
28017
|
if (a !== b) return false;
|
|
27841
28018
|
}
|
|
27842
28019
|
return true;
|
|
@@ -28017,7 +28194,7 @@ async function synthesizeLocally(opts) {
|
|
|
28017
28194
|
async function healStaleAnalysisConfig(globals) {
|
|
28018
28195
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
28019
28196
|
const standardPath = projectPath(STANDARD_FILE);
|
|
28020
|
-
if (!(0,
|
|
28197
|
+
if (!(0, import_node_fs55.existsSync)(configPath) || !(0, import_node_fs55.existsSync)(standardPath)) return;
|
|
28021
28198
|
const validation = validatePatternIds();
|
|
28022
28199
|
if (validation.status !== "invalid") return;
|
|
28023
28200
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
@@ -28114,17 +28291,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
28114
28291
|
async function installSkills(force, step) {
|
|
28115
28292
|
step("Installing skills");
|
|
28116
28293
|
const dataDir = resolveDataDir2();
|
|
28117
|
-
const skillsSource = (0,
|
|
28294
|
+
const skillsSource = (0, import_node_path39.join)(dataDir, "skills");
|
|
28118
28295
|
const skillsDest = ".claude/skills";
|
|
28119
28296
|
let skillsInstalled = 0;
|
|
28120
28297
|
for (const skill of SKILLS) {
|
|
28121
|
-
const src = (0,
|
|
28122
|
-
const dest = (0,
|
|
28123
|
-
if (!(0,
|
|
28298
|
+
const src = (0, import_node_path39.join)(skillsSource, skill);
|
|
28299
|
+
const dest = (0, import_node_path39.join)(skillsDest, skill);
|
|
28300
|
+
if (!(0, import_node_fs55.existsSync)(src)) {
|
|
28124
28301
|
printWarn(` Skill data not found: ${skill}`);
|
|
28125
28302
|
continue;
|
|
28126
28303
|
}
|
|
28127
|
-
if ((0,
|
|
28304
|
+
if ((0, import_node_fs55.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
28128
28305
|
skillsInstalled++;
|
|
28129
28306
|
continue;
|
|
28130
28307
|
}
|
|
@@ -28263,7 +28440,7 @@ function registerInitCommand(program2) {
|
|
|
28263
28440
|
const staleMarker = clearStalePluginMarker();
|
|
28264
28441
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
28265
28442
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
28266
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
28443
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs55.existsSync)(m));
|
|
28267
28444
|
if (!isProject) {
|
|
28268
28445
|
printError("No project detected in the current directory.");
|
|
28269
28446
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -28353,7 +28530,7 @@ function registerInitCommand(program2) {
|
|
|
28353
28530
|
printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
|
|
28354
28531
|
}
|
|
28355
28532
|
await scaffoldProject(step, defaultsOnly);
|
|
28356
|
-
const globalVerityDir = (0,
|
|
28533
|
+
const globalVerityDir = (0, import_node_path39.join)(process.env.HOME ?? "", ".verity");
|
|
28357
28534
|
await (0, import_promises19.mkdir)(globalVerityDir, { recursive: true });
|
|
28358
28535
|
console.log("");
|
|
28359
28536
|
step("Wiring Claude Code hooks");
|
|
@@ -28422,7 +28599,7 @@ function registerInitCommand(program2) {
|
|
|
28422
28599
|
}
|
|
28423
28600
|
step("Your project's Standard");
|
|
28424
28601
|
let haveStandard = false;
|
|
28425
|
-
if ((0,
|
|
28602
|
+
if ((0, import_node_fs55.existsSync)(projectPath(STANDARD_FILE))) {
|
|
28426
28603
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
28427
28604
|
haveStandard = true;
|
|
28428
28605
|
} else {
|
|
@@ -28452,7 +28629,7 @@ function registerInitCommand(program2) {
|
|
|
28452
28629
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
28453
28630
|
init: {
|
|
28454
28631
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28455
|
-
cli_version: true ? "0.33.0
|
|
28632
|
+
cli_version: true ? "0.33.0" : "dev"
|
|
28456
28633
|
}
|
|
28457
28634
|
});
|
|
28458
28635
|
} catch (err) {
|
|
@@ -28502,8 +28679,8 @@ function registerInitCommand(program2) {
|
|
|
28502
28679
|
}
|
|
28503
28680
|
|
|
28504
28681
|
// src/commands/uninstall.ts
|
|
28505
|
-
var
|
|
28506
|
-
var
|
|
28682
|
+
var import_node_fs56 = require("node:fs");
|
|
28683
|
+
var import_node_path40 = require("node:path");
|
|
28507
28684
|
function registerUninstallCommand(program2) {
|
|
28508
28685
|
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
28686
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -28512,11 +28689,11 @@ function registerUninstallCommand(program2) {
|
|
|
28512
28689
|
const actions = [];
|
|
28513
28690
|
const skillsRoot = projectPath(".claude/skills");
|
|
28514
28691
|
for (const name of PROJECT_SKILL_NAMES) {
|
|
28515
|
-
const dir = (0,
|
|
28516
|
-
if ((0,
|
|
28692
|
+
const dir = (0, import_node_path40.join)(skillsRoot, name);
|
|
28693
|
+
if ((0, import_node_fs56.existsSync)(dir)) {
|
|
28517
28694
|
actions.push({
|
|
28518
28695
|
label: `Remove .claude/skills/${name}/`,
|
|
28519
|
-
apply: () => (0,
|
|
28696
|
+
apply: () => (0, import_node_fs56.rmSync)(dir, { recursive: true, force: true })
|
|
28520
28697
|
});
|
|
28521
28698
|
}
|
|
28522
28699
|
}
|
|
@@ -28530,24 +28707,24 @@ function registerUninstallCommand(program2) {
|
|
|
28530
28707
|
});
|
|
28531
28708
|
}
|
|
28532
28709
|
const verityDir = projectPath(VERITY_DIR);
|
|
28533
|
-
if ((0,
|
|
28710
|
+
if ((0, import_node_fs56.existsSync)(verityDir)) {
|
|
28534
28711
|
actions.push({
|
|
28535
28712
|
label: `Remove ${VERITY_DIR}/`,
|
|
28536
|
-
apply: () => (0,
|
|
28713
|
+
apply: () => (0, import_node_fs56.rmSync)(verityDir, { recursive: true, force: true })
|
|
28537
28714
|
});
|
|
28538
28715
|
}
|
|
28539
28716
|
if (!keepVerityMd) {
|
|
28540
28717
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
28541
|
-
if ((0,
|
|
28718
|
+
if ((0, import_node_fs56.existsSync)(verityMd)) {
|
|
28542
28719
|
actions.push({
|
|
28543
28720
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
28544
|
-
apply: () => (0,
|
|
28721
|
+
apply: () => (0, import_node_fs56.rmSync)(verityMd, { force: true })
|
|
28545
28722
|
});
|
|
28546
28723
|
}
|
|
28547
28724
|
}
|
|
28548
28725
|
const cleanupEmptyDir = (path) => {
|
|
28549
|
-
if ((0,
|
|
28550
|
-
(0,
|
|
28726
|
+
if ((0, import_node_fs56.existsSync)(path) && (0, import_node_fs56.statSync)(path).isDirectory() && (0, import_node_fs56.readdirSync)(path).length === 0) {
|
|
28727
|
+
(0, import_node_fs56.rmdirSync)(path);
|
|
28551
28728
|
}
|
|
28552
28729
|
};
|
|
28553
28730
|
actions.push({
|
|
@@ -28558,11 +28735,11 @@ function registerUninstallCommand(program2) {
|
|
|
28558
28735
|
}
|
|
28559
28736
|
});
|
|
28560
28737
|
const home = process.env.HOME ?? "";
|
|
28561
|
-
const globalVerityDir = (0,
|
|
28562
|
-
if (purgeGlobal && (0,
|
|
28738
|
+
const globalVerityDir = (0, import_node_path40.join)(home, ".verity");
|
|
28739
|
+
if (purgeGlobal && (0, import_node_fs56.existsSync)(globalVerityDir)) {
|
|
28563
28740
|
actions.push({
|
|
28564
28741
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
28565
|
-
apply: () => (0,
|
|
28742
|
+
apply: () => (0, import_node_fs56.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
28566
28743
|
});
|
|
28567
28744
|
}
|
|
28568
28745
|
if (actions.length === 0) {
|
|
@@ -28756,8 +28933,8 @@ function registerTaskCommands(program2) {
|
|
|
28756
28933
|
}
|
|
28757
28934
|
|
|
28758
28935
|
// src/commands/reset.ts
|
|
28759
|
-
var
|
|
28760
|
-
var
|
|
28936
|
+
var import_node_fs57 = require("node:fs");
|
|
28937
|
+
var import_node_path41 = require("node:path");
|
|
28761
28938
|
function registerResetCommand(program2) {
|
|
28762
28939
|
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
28940
|
const globals = program2.opts();
|
|
@@ -28794,11 +28971,11 @@ function registerResetCommand(program2) {
|
|
|
28794
28971
|
}
|
|
28795
28972
|
const cacheDir = projectPath(CACHE_DIR);
|
|
28796
28973
|
let purged = 0;
|
|
28797
|
-
if ((0,
|
|
28798
|
-
for (const entry of (0,
|
|
28974
|
+
if ((0, import_node_fs57.existsSync)(cacheDir)) {
|
|
28975
|
+
for (const entry of (0, import_node_fs57.readdirSync)(cacheDir)) {
|
|
28799
28976
|
if (entry.startsWith("pending-")) {
|
|
28800
28977
|
try {
|
|
28801
|
-
(0,
|
|
28978
|
+
(0, import_node_fs57.unlinkSync)((0, import_node_path41.join)(cacheDir, entry));
|
|
28802
28979
|
purged++;
|
|
28803
28980
|
} catch {
|
|
28804
28981
|
}
|
|
@@ -28813,19 +28990,19 @@ function registerResetCommand(program2) {
|
|
|
28813
28990
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
28814
28991
|
];
|
|
28815
28992
|
for (const file of filesToClear) {
|
|
28816
|
-
if ((0,
|
|
28993
|
+
if ((0, import_node_fs57.existsSync)(file)) {
|
|
28817
28994
|
try {
|
|
28818
|
-
(0,
|
|
28995
|
+
(0, import_node_fs57.writeFileSync)(file, "");
|
|
28819
28996
|
} catch {
|
|
28820
28997
|
}
|
|
28821
28998
|
}
|
|
28822
28999
|
}
|
|
28823
29000
|
if (opts.all) {
|
|
28824
29001
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
28825
|
-
if ((0,
|
|
28826
|
-
for (const entry of (0,
|
|
29002
|
+
if ((0, import_node_fs57.existsSync)(logsDir)) {
|
|
29003
|
+
for (const entry of (0, import_node_fs57.readdirSync)(logsDir)) {
|
|
28827
29004
|
try {
|
|
28828
|
-
(0,
|
|
29005
|
+
(0, import_node_fs57.unlinkSync)((0, import_node_path41.join)(logsDir, entry));
|
|
28829
29006
|
} catch {
|
|
28830
29007
|
}
|
|
28831
29008
|
}
|
|
@@ -28837,7 +29014,7 @@ function registerResetCommand(program2) {
|
|
|
28837
29014
|
}
|
|
28838
29015
|
|
|
28839
29016
|
// src/commands/reflect.ts
|
|
28840
|
-
var
|
|
29017
|
+
var import_node_fs58 = require("node:fs");
|
|
28841
29018
|
|
|
28842
29019
|
// src/lib/reflection-globs.ts
|
|
28843
29020
|
var MAX_GLOBS = 6;
|
|
@@ -28875,7 +29052,7 @@ async function writeNodeToDisk(args) {
|
|
|
28875
29052
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
28876
29053
|
);
|
|
28877
29054
|
if (written === 0) return false;
|
|
28878
|
-
return (0,
|
|
29055
|
+
return (0, import_node_fs58.existsSync)(projectPath(`${VERITY_DIR}/memory/${args.filePath}`));
|
|
28879
29056
|
} catch {
|
|
28880
29057
|
return false;
|
|
28881
29058
|
}
|
|
@@ -28954,7 +29131,7 @@ function registerReflectCommand(program2) {
|
|
|
28954
29131
|
const fileGlobs = explicitGlobs.length > 0 ? explicitGlobs : derivedGlobs.length > 0 ? derivedGlobs : inheritedGlobs;
|
|
28955
29132
|
const result = await apiRequest({
|
|
28956
29133
|
method: "POST",
|
|
28957
|
-
path: "/compound/
|
|
29134
|
+
path: "/compound/reflect",
|
|
28958
29135
|
serviceUrl,
|
|
28959
29136
|
token,
|
|
28960
29137
|
body: {
|
|
@@ -28987,6 +29164,8 @@ function registerReflectCommand(program2) {
|
|
|
28987
29164
|
const nodeId = result.data.node_id;
|
|
28988
29165
|
const filePath = result.data.file_path;
|
|
28989
29166
|
const viewUrl = typeof result.data.view_url === "string" ? result.data.view_url : null;
|
|
29167
|
+
const recordedSource = typeof result.data.source === "string" ? result.data.source : source;
|
|
29168
|
+
const recordedAsUser = recordedSource === "user";
|
|
28990
29169
|
const content = typeof result.data.content === "string" ? result.data.content : null;
|
|
28991
29170
|
const synced = content !== null && await writeNodeToDisk({ filePath, content, nodeId });
|
|
28992
29171
|
printInfo(
|
|
@@ -28994,8 +29173,13 @@ function registerReflectCommand(program2) {
|
|
|
28994
29173
|
);
|
|
28995
29174
|
if (viewUrl) printInfo(` ${viewUrl}`);
|
|
28996
29175
|
printInfo(
|
|
28997
|
-
|
|
29176
|
+
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
29177
|
);
|
|
29178
|
+
if (recordedSource !== source) {
|
|
29179
|
+
printWarn(
|
|
29180
|
+
`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.`
|
|
29181
|
+
);
|
|
29182
|
+
}
|
|
28999
29183
|
if (fileGlobs.length === 0) {
|
|
29000
29184
|
printWarn(
|
|
29001
29185
|
'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 +29551,8 @@ function registerTelemetryCommands(program2) {
|
|
|
29367
29551
|
}
|
|
29368
29552
|
|
|
29369
29553
|
// src/cli.ts
|
|
29370
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.33.0
|
|
29371
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.0
|
|
29554
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.33.0").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) => {
|
|
29555
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.0");
|
|
29372
29556
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
29373
29557
|
try {
|
|
29374
29558
|
await foldLegacyLocalCredential();
|