@codacy/verity-cli 0.34.0-experimental.145d0fb → 0.34.0-experimental.37a6dcf
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 +77 -0
- package/bin/verity.js +1016 -888
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -17104,8 +17104,107 @@ async function applyMomentSelection(moments) {
|
|
|
17104
17104
|
}
|
|
17105
17105
|
|
|
17106
17106
|
// src/lib/project-config.ts
|
|
17107
|
+
var import_node_fs6 = require("node:fs");
|
|
17108
|
+
var import_node_path8 = require("node:path");
|
|
17109
|
+
|
|
17110
|
+
// src/lib/repo-controlled.ts
|
|
17107
17111
|
var import_node_fs5 = require("node:fs");
|
|
17108
17112
|
var import_node_path7 = require("node:path");
|
|
17113
|
+
|
|
17114
|
+
// src/lib/hardened-git.ts
|
|
17115
|
+
var import_node_child_process5 = require("node:child_process");
|
|
17116
|
+
var HARDENED_CONFIG_ARGS = [
|
|
17117
|
+
"-c",
|
|
17118
|
+
"core.fsmonitor=false",
|
|
17119
|
+
"-c",
|
|
17120
|
+
"core.pager=cat",
|
|
17121
|
+
"-c",
|
|
17122
|
+
"log.showSignature=false"
|
|
17123
|
+
];
|
|
17124
|
+
var DIFF_READ_FLAGS = ["--no-ext-diff", "--no-textconv"];
|
|
17125
|
+
var DEFAULT_GIT_TIMEOUT_MS = 6e4;
|
|
17126
|
+
var DEFAULT_GIT_MAX_BUFFER = 64 * 1024 * 1024;
|
|
17127
|
+
function hardenedGitEnv(base = process.env) {
|
|
17128
|
+
const env = {};
|
|
17129
|
+
for (const [key, value] of Object.entries(base)) {
|
|
17130
|
+
if (key.startsWith("GIT_")) continue;
|
|
17131
|
+
env[key] = value;
|
|
17132
|
+
}
|
|
17133
|
+
env.GIT_OPTIONAL_LOCKS = "0";
|
|
17134
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
17135
|
+
return env;
|
|
17136
|
+
}
|
|
17137
|
+
function hardenedGitArgv(args2) {
|
|
17138
|
+
return [...HARDENED_CONFIG_ARGS, ...args2];
|
|
17139
|
+
}
|
|
17140
|
+
function classifyError(err2) {
|
|
17141
|
+
const e = err2;
|
|
17142
|
+
const stderr = typeof e?.stderr === "string" ? e.stderr : e?.stderr ? e.stderr.toString("utf-8") : "";
|
|
17143
|
+
if (e?.code === "ETIMEDOUT" || e?.killed && e?.signal === "SIGTERM") return { ok: false, error: "timeout", stderr };
|
|
17144
|
+
if (e?.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") return { ok: false, error: "too_large", stderr };
|
|
17145
|
+
return { ok: false, error: "failed", stderr };
|
|
17146
|
+
}
|
|
17147
|
+
function runGitSync(cwd, args2, opts = {}) {
|
|
17148
|
+
try {
|
|
17149
|
+
const stdout = (0, import_node_child_process5.execFileSync)("git", hardenedGitArgv(args2), {
|
|
17150
|
+
cwd,
|
|
17151
|
+
env: hardenedGitEnv(),
|
|
17152
|
+
encoding: "utf-8",
|
|
17153
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
17154
|
+
timeout: opts.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS,
|
|
17155
|
+
maxBuffer: opts.maxBuffer ?? DEFAULT_GIT_MAX_BUFFER
|
|
17156
|
+
});
|
|
17157
|
+
return { ok: true, stdout };
|
|
17158
|
+
} catch (err2) {
|
|
17159
|
+
return classifyError(err2);
|
|
17160
|
+
}
|
|
17161
|
+
}
|
|
17162
|
+
function runGit(cwd, args2, opts = {}) {
|
|
17163
|
+
return new Promise((resolvePromise) => {
|
|
17164
|
+
(0, import_node_child_process5.execFile)(
|
|
17165
|
+
"git",
|
|
17166
|
+
hardenedGitArgv(args2),
|
|
17167
|
+
{
|
|
17168
|
+
cwd,
|
|
17169
|
+
env: hardenedGitEnv(),
|
|
17170
|
+
encoding: "utf-8",
|
|
17171
|
+
timeout: opts.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS,
|
|
17172
|
+
maxBuffer: opts.maxBuffer ?? DEFAULT_GIT_MAX_BUFFER
|
|
17173
|
+
},
|
|
17174
|
+
(err2, stdout, stderr) => {
|
|
17175
|
+
if (err2) {
|
|
17176
|
+
const e = err2;
|
|
17177
|
+
e.stderr = stderr;
|
|
17178
|
+
resolvePromise(classifyError(e));
|
|
17179
|
+
return;
|
|
17180
|
+
}
|
|
17181
|
+
resolvePromise({ ok: true, stdout });
|
|
17182
|
+
}
|
|
17183
|
+
);
|
|
17184
|
+
});
|
|
17185
|
+
}
|
|
17186
|
+
|
|
17187
|
+
// src/lib/repo-controlled.ts
|
|
17188
|
+
function repoControlled(worktree, rel) {
|
|
17189
|
+
const parts2 = rel.split("/").filter(Boolean);
|
|
17190
|
+
for (let i2 = 1; i2 <= parts2.length; i2++) {
|
|
17191
|
+
let st;
|
|
17192
|
+
try {
|
|
17193
|
+
st = (0, import_node_fs5.lstatSync)((0, import_node_path7.join)(worktree, ...parts2.slice(0, i2)));
|
|
17194
|
+
} catch (err2) {
|
|
17195
|
+
const code = err2?.code;
|
|
17196
|
+
if (code === "ENOENT" || code === "ENOTDIR") return null;
|
|
17197
|
+
return "unverified";
|
|
17198
|
+
}
|
|
17199
|
+
if (st.isSymbolicLink()) return "symlink";
|
|
17200
|
+
if (i2 === parts2.length && !st.isFile()) return "symlink";
|
|
17201
|
+
}
|
|
17202
|
+
const r = runGitSync(worktree, ["ls-files", "-z", "--", rel], { timeoutMs: 5e3 });
|
|
17203
|
+
if (!r.ok) return "unverified";
|
|
17204
|
+
return r.stdout.length > 0 ? "tracked" : null;
|
|
17205
|
+
}
|
|
17206
|
+
|
|
17207
|
+
// src/lib/project-config.ts
|
|
17109
17208
|
var DEFAULTS = { git_moments: [] };
|
|
17110
17209
|
function isMoment(value) {
|
|
17111
17210
|
return value === "commit" || value === "push";
|
|
@@ -17115,14 +17214,14 @@ function parseMoments(raw) {
|
|
|
17115
17214
|
}
|
|
17116
17215
|
function readConfigFile(path) {
|
|
17117
17216
|
try {
|
|
17118
|
-
if (!(0,
|
|
17119
|
-
const raw = JSON.parse((0,
|
|
17217
|
+
if (!(0, import_node_fs6.existsSync)(path)) return null;
|
|
17218
|
+
const raw = JSON.parse((0, import_node_fs6.readFileSync)(path, "utf-8"));
|
|
17120
17219
|
const moments = Array.isArray(raw.git_moments) ? raw.git_moments.filter(isMoment) : [];
|
|
17121
17220
|
const source2 = raw.git_moments_source === "user" || raw.git_moments_source === "init" ? raw.git_moments_source : void 0;
|
|
17122
17221
|
return {
|
|
17123
17222
|
git_moments: [...new Set(moments)],
|
|
17124
17223
|
...source2 ? { git_moments_source: source2 } : {},
|
|
17125
|
-
...raw.formal === "push" ? { formal:
|
|
17224
|
+
...raw.formal === "push" || raw.formal === "off" ? { formal: raw.formal } : {}
|
|
17126
17225
|
};
|
|
17127
17226
|
} catch {
|
|
17128
17227
|
return DEFAULTS;
|
|
@@ -17133,20 +17232,41 @@ function candidates() {
|
|
|
17133
17232
|
const out2 = [{ path: local, source: "local" }];
|
|
17134
17233
|
const main = mainWorktreeRoot();
|
|
17135
17234
|
if (main) {
|
|
17136
|
-
const inherited = (0,
|
|
17235
|
+
const inherited = (0, import_node_path8.join)(main, PROJECT_CONFIG_FILE);
|
|
17137
17236
|
if (inherited !== local) out2.push({ path: inherited, source: "main-worktree" });
|
|
17138
17237
|
}
|
|
17139
17238
|
return out2;
|
|
17140
17239
|
}
|
|
17141
|
-
function
|
|
17240
|
+
function formalRefusal(path) {
|
|
17241
|
+
return repoControlled((0, import_node_path8.dirname)((0, import_node_path8.dirname)(path)), PROJECT_CONFIG_FILE);
|
|
17242
|
+
}
|
|
17243
|
+
function readProjectConfigRaw() {
|
|
17142
17244
|
for (const { path, source: source2 } of candidates()) {
|
|
17143
17245
|
const cfg = readConfigFile(path);
|
|
17144
17246
|
if (cfg) return { ...cfg, source: source2, path };
|
|
17145
17247
|
}
|
|
17146
17248
|
return { ...DEFAULTS, source: "default" };
|
|
17147
17249
|
}
|
|
17250
|
+
function readProjectConfig() {
|
|
17251
|
+
const cfg = readProjectConfigRaw();
|
|
17252
|
+
if (cfg.formal !== "push" || !cfg.path) return cfg;
|
|
17253
|
+
const refused2 = formalRefusal(cfg.path);
|
|
17254
|
+
if (!refused2) return cfg;
|
|
17255
|
+
const { formal: _dropped, ...rest } = cfg;
|
|
17256
|
+
return { ...rest, formal_refused: refused2 };
|
|
17257
|
+
}
|
|
17258
|
+
function formalRefusalMessage(reason) {
|
|
17259
|
+
switch (reason) {
|
|
17260
|
+
case "tracked":
|
|
17261
|
+
return ".verity/config.json is tracked in git, so its formal setting is ignored (a repository cannot switch formal verification on) \u2014 untrack it with: git rm --cached .verity/config.json";
|
|
17262
|
+
case "symlink":
|
|
17263
|
+
return ".verity/config.json is reached through a symlink, so its formal setting is ignored";
|
|
17264
|
+
case "unverified":
|
|
17265
|
+
return "could not confirm with git that .verity/config.json is untracked, so its formal setting is ignored";
|
|
17266
|
+
}
|
|
17267
|
+
}
|
|
17148
17268
|
function writeProjectConfig(patch) {
|
|
17149
|
-
const { git_moments, git_moments_source, formal } =
|
|
17269
|
+
const { git_moments, git_moments_source, formal } = readProjectConfigRaw();
|
|
17150
17270
|
const next = {
|
|
17151
17271
|
git_moments,
|
|
17152
17272
|
...git_moments_source ? { git_moments_source } : {},
|
|
@@ -17154,8 +17274,8 @@ function writeProjectConfig(patch) {
|
|
|
17154
17274
|
...patch
|
|
17155
17275
|
};
|
|
17156
17276
|
const target = projectPath(PROJECT_CONFIG_FILE);
|
|
17157
|
-
(0,
|
|
17158
|
-
(0,
|
|
17277
|
+
(0, import_node_fs6.mkdirSync)((0, import_node_path8.dirname)(target), { recursive: true });
|
|
17278
|
+
(0, import_node_fs6.writeFileSync)(target, JSON.stringify(next, null, 2) + "\n");
|
|
17159
17279
|
return next;
|
|
17160
17280
|
}
|
|
17161
17281
|
function resolveGuardMoments(explicit) {
|
|
@@ -17164,11 +17284,11 @@ function resolveGuardMoments(explicit) {
|
|
|
17164
17284
|
}
|
|
17165
17285
|
|
|
17166
17286
|
// src/lib/plugin-ownership.ts
|
|
17167
|
-
var
|
|
17287
|
+
var import_node_fs9 = require("node:fs");
|
|
17168
17288
|
|
|
17169
17289
|
// src/lib/which.ts
|
|
17170
|
-
var
|
|
17171
|
-
var
|
|
17290
|
+
var import_node_fs7 = require("node:fs");
|
|
17291
|
+
var import_node_path9 = require("node:path");
|
|
17172
17292
|
function executableExtensions(platform4, pathext) {
|
|
17173
17293
|
if (platform4 !== "win32") return [""];
|
|
17174
17294
|
const raw = (pathext ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
|
|
@@ -17186,14 +17306,14 @@ function whichSync(bin, opts = {}) {
|
|
|
17186
17306
|
if (!rawPath) return null;
|
|
17187
17307
|
const exts = executableExtensions(platform4, opts.pathext ?? process.env.PATHEXT);
|
|
17188
17308
|
const real = opts.real ?? true;
|
|
17189
|
-
for (const dir of rawPath.split(
|
|
17309
|
+
for (const dir of rawPath.split(import_node_path9.delimiter)) {
|
|
17190
17310
|
if (!dir) continue;
|
|
17191
17311
|
for (const ext of exts) {
|
|
17192
|
-
const candidate = (0,
|
|
17312
|
+
const candidate = (0, import_node_path9.join)(dir, bin + ext);
|
|
17193
17313
|
try {
|
|
17194
|
-
if (!(0,
|
|
17195
|
-
if (platform4 !== "win32") (0,
|
|
17196
|
-
return real ? (0,
|
|
17314
|
+
if (!(0, import_node_fs7.statSync)(candidate).isFile()) continue;
|
|
17315
|
+
if (platform4 !== "win32") (0, import_node_fs7.accessSync)(candidate, import_node_fs7.constants.X_OK);
|
|
17316
|
+
return real ? (0, import_node_fs7.realpathSync)(candidate) : candidate;
|
|
17197
17317
|
} catch {
|
|
17198
17318
|
continue;
|
|
17199
17319
|
}
|
|
@@ -17204,10 +17324,10 @@ function whichSync(bin, opts = {}) {
|
|
|
17204
17324
|
|
|
17205
17325
|
// src/lib/plugin-ownership.ts
|
|
17206
17326
|
var import_node_os2 = require("node:os");
|
|
17207
|
-
var
|
|
17327
|
+
var import_node_path10 = require("node:path");
|
|
17208
17328
|
|
|
17209
17329
|
// src/lib/stderr-log.ts
|
|
17210
|
-
var
|
|
17330
|
+
var import_node_fs8 = require("node:fs");
|
|
17211
17331
|
var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
|
|
17212
17332
|
var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
17213
17333
|
function scrub(s) {
|
|
@@ -17220,9 +17340,9 @@ function append(text) {
|
|
|
17220
17340
|
try {
|
|
17221
17341
|
const dir = projectPath(DEBUG_LOG_DIR);
|
|
17222
17342
|
const file = projectPath(STDERR_LOG_FILE);
|
|
17223
|
-
(0,
|
|
17343
|
+
(0, import_node_fs8.mkdirSync)(dir, { recursive: true });
|
|
17224
17344
|
rotateIfNeeded(file);
|
|
17225
|
-
(0,
|
|
17345
|
+
(0, import_node_fs8.appendFileSync)(file, text);
|
|
17226
17346
|
} catch {
|
|
17227
17347
|
}
|
|
17228
17348
|
}
|
|
@@ -17270,8 +17390,8 @@ function markerPath() {
|
|
|
17270
17390
|
}
|
|
17271
17391
|
function readMarker() {
|
|
17272
17392
|
try {
|
|
17273
|
-
if (!(0,
|
|
17274
|
-
const raw = JSON.parse((0,
|
|
17393
|
+
if (!(0, import_node_fs9.existsSync)(markerPath())) return null;
|
|
17394
|
+
const raw = JSON.parse((0, import_node_fs9.readFileSync)(markerPath(), "utf-8"));
|
|
17275
17395
|
const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
|
|
17276
17396
|
if (!pluginRoot || CONTROL_CHARS2.test(pluginRoot)) return null;
|
|
17277
17397
|
const version = typeof raw.version === "string" && !CONTROL_CHARS2.test(raw.version) ? raw.version : null;
|
|
@@ -17289,23 +17409,23 @@ function recordPluginOwnership(sessionId) {
|
|
|
17289
17409
|
const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
|
|
17290
17410
|
if (!pluginRoot) return;
|
|
17291
17411
|
try {
|
|
17292
|
-
(0,
|
|
17412
|
+
(0, import_node_fs9.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
17293
17413
|
const marker = {
|
|
17294
17414
|
session_id: sessionId,
|
|
17295
17415
|
plugin_root: pluginRoot,
|
|
17296
17416
|
version: process.env.VERITY_PLUGIN_VERSION || null,
|
|
17297
17417
|
ts: Math.floor(Date.now() / 1e3)
|
|
17298
17418
|
};
|
|
17299
|
-
(0,
|
|
17419
|
+
(0, import_node_fs9.writeFileSync)(markerPath(), JSON.stringify(marker));
|
|
17300
17420
|
} catch {
|
|
17301
17421
|
}
|
|
17302
17422
|
}
|
|
17303
17423
|
function claudeConfigDir() {
|
|
17304
|
-
return process.env.CLAUDE_CONFIG_DIR || (0,
|
|
17424
|
+
return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path10.join)((0, import_node_os2.homedir)(), ".claude");
|
|
17305
17425
|
}
|
|
17306
17426
|
function readJsonFile(path) {
|
|
17307
17427
|
try {
|
|
17308
|
-
const parsed = JSON.parse((0,
|
|
17428
|
+
const parsed = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf-8"));
|
|
17309
17429
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
17310
17430
|
} catch {
|
|
17311
17431
|
return null;
|
|
@@ -17313,9 +17433,9 @@ function readJsonFile(path) {
|
|
|
17313
17433
|
}
|
|
17314
17434
|
function enabledPluginSetting(key) {
|
|
17315
17435
|
const files = [
|
|
17316
|
-
projectPath((0,
|
|
17317
|
-
projectPath((0,
|
|
17318
|
-
(0,
|
|
17436
|
+
projectPath((0, import_node_path10.join)(".claude", "settings.local.json")),
|
|
17437
|
+
projectPath((0, import_node_path10.join)(".claude", "settings.json")),
|
|
17438
|
+
(0, import_node_path10.join)(claudeConfigDir(), "settings.json")
|
|
17319
17439
|
];
|
|
17320
17440
|
for (const file of files) {
|
|
17321
17441
|
const map = readJsonFile(file)?.enabledPlugins;
|
|
@@ -17327,11 +17447,11 @@ function enabledPluginSetting(key) {
|
|
|
17327
17447
|
}
|
|
17328
17448
|
function marketplaceLocations() {
|
|
17329
17449
|
const out2 = /* @__PURE__ */ new Map();
|
|
17330
|
-
const known = readJsonFile((0,
|
|
17450
|
+
const known = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
17331
17451
|
if (!known) return out2;
|
|
17332
17452
|
for (const [name2, entry] of Object.entries(known)) {
|
|
17333
17453
|
const loc2 = entry?.installLocation;
|
|
17334
|
-
if (typeof loc2 === "string" && loc2) out2.set(name2, (0,
|
|
17454
|
+
if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path10.resolve)(loc2));
|
|
17335
17455
|
}
|
|
17336
17456
|
return out2;
|
|
17337
17457
|
}
|
|
@@ -17345,7 +17465,7 @@ function globalVerityVersion() {
|
|
|
17345
17465
|
const entry = verityPathEntry();
|
|
17346
17466
|
if (!entry) return null;
|
|
17347
17467
|
try {
|
|
17348
|
-
const pkg = readJsonFile((0,
|
|
17468
|
+
const pkg = readJsonFile((0, import_node_path10.join)((0, import_node_path10.dirname)((0, import_node_fs9.realpathSync)(entry)), "..", "package.json"));
|
|
17349
17469
|
if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
|
|
17350
17470
|
return pkg.version;
|
|
17351
17471
|
} catch {
|
|
@@ -17362,7 +17482,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
|
|
|
17362
17482
|
function marketplaceConflict() {
|
|
17363
17483
|
const wanted = VERITY_MARKETPLACE;
|
|
17364
17484
|
for (const file of ["settings.json", "settings.local.json"]) {
|
|
17365
|
-
const path = (0,
|
|
17485
|
+
const path = (0, import_node_path10.join)(claudeConfigDir(), file);
|
|
17366
17486
|
const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
|
|
17367
17487
|
const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
|
|
17368
17488
|
if (entry2 && typeof entry2 === "object") {
|
|
@@ -17372,7 +17492,7 @@ function marketplaceConflict() {
|
|
|
17372
17492
|
}
|
|
17373
17493
|
}
|
|
17374
17494
|
}
|
|
17375
|
-
const known = readJsonFile((0,
|
|
17495
|
+
const known = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
17376
17496
|
const entry = known?.[wanted];
|
|
17377
17497
|
if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
|
|
17378
17498
|
return { name: wanted, declaredAs: describeSource(entry.source) };
|
|
@@ -17393,7 +17513,7 @@ function describeSource(src) {
|
|
|
17393
17513
|
return target ? `${kind} \u2192 ${target}` : kind;
|
|
17394
17514
|
}
|
|
17395
17515
|
function legacyMarketplaceInstall() {
|
|
17396
|
-
const plugins = readJsonFile((0,
|
|
17516
|
+
const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17397
17517
|
if (!plugins || typeof plugins !== "object") return null;
|
|
17398
17518
|
for (const key of Object.keys(plugins)) {
|
|
17399
17519
|
const at = key.lastIndexOf("@");
|
|
@@ -17405,13 +17525,13 @@ function legacyMarketplaceInstall() {
|
|
|
17405
17525
|
}
|
|
17406
17526
|
function realpathOr(p) {
|
|
17407
17527
|
try {
|
|
17408
|
-
return
|
|
17528
|
+
return import_node_fs9.realpathSync.native(p);
|
|
17409
17529
|
} catch {
|
|
17410
|
-
return (0,
|
|
17530
|
+
return (0, import_node_path10.resolve)(p);
|
|
17411
17531
|
}
|
|
17412
17532
|
}
|
|
17413
17533
|
function isWithin(want, dir) {
|
|
17414
|
-
return want === dir || want.startsWith(dir +
|
|
17534
|
+
return want === dir || want.startsWith(dir + import_node_path10.sep);
|
|
17415
17535
|
}
|
|
17416
17536
|
function entryAppliesHere(entry, here) {
|
|
17417
17537
|
const e = entry;
|
|
@@ -17421,9 +17541,9 @@ function entryAppliesHere(entry, here) {
|
|
|
17421
17541
|
return forProject === here;
|
|
17422
17542
|
}
|
|
17423
17543
|
function registrySays(pluginRoot) {
|
|
17424
|
-
const plugins = readJsonFile((0,
|
|
17544
|
+
const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17425
17545
|
if (!plugins || typeof plugins !== "object") return "unverified";
|
|
17426
|
-
const want = (0,
|
|
17546
|
+
const want = (0, import_node_path10.resolve)(pluginRoot);
|
|
17427
17547
|
const here = realpathOr(repoRoot());
|
|
17428
17548
|
const markets = marketplaceLocations();
|
|
17429
17549
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -17432,15 +17552,15 @@ function registrySays(pluginRoot) {
|
|
|
17432
17552
|
const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
|
|
17433
17553
|
const claims = applicable.some((entry) => {
|
|
17434
17554
|
const installPath = entry?.installPath;
|
|
17435
|
-
return typeof installPath === "string" && (0,
|
|
17555
|
+
return typeof installPath === "string" && (0, import_node_path10.resolve)(installPath) === want;
|
|
17436
17556
|
}) || source2 !== void 0 && applicable.length > 0 && isWithin(want, source2);
|
|
17437
17557
|
if (claims) {
|
|
17438
17558
|
if (enabledPluginSetting(key) === false) return "gone";
|
|
17439
|
-
return (0,
|
|
17559
|
+
return (0, import_node_fs9.existsSync)(pluginRoot) ? "live" : "gone";
|
|
17440
17560
|
}
|
|
17441
17561
|
}
|
|
17442
|
-
const managed = (0,
|
|
17443
|
-
return want === managed || want.startsWith(managed +
|
|
17562
|
+
const managed = (0, import_node_path10.resolve)((0, import_node_path10.join)(claudeConfigDir(), "plugins", "cache"));
|
|
17563
|
+
return want === managed || want.startsWith(managed + import_node_path10.sep) ? "gone" : "unverified";
|
|
17444
17564
|
}
|
|
17445
17565
|
var _live = /* @__PURE__ */ new Map();
|
|
17446
17566
|
function pluginLiveness(pluginRoot) {
|
|
@@ -17454,7 +17574,7 @@ function clearStalePluginMarker() {
|
|
|
17454
17574
|
const marker = readMarker();
|
|
17455
17575
|
if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
|
|
17456
17576
|
try {
|
|
17457
|
-
(0,
|
|
17577
|
+
(0, import_node_fs9.rmSync)(markerPath(), { force: true });
|
|
17458
17578
|
} catch {
|
|
17459
17579
|
return null;
|
|
17460
17580
|
}
|
|
@@ -17482,7 +17602,7 @@ function pluginActiveHere() {
|
|
|
17482
17602
|
return activePluginInstall() !== null;
|
|
17483
17603
|
}
|
|
17484
17604
|
function registeredVerityPlugin() {
|
|
17485
|
-
const plugins = readJsonFile((0,
|
|
17605
|
+
const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17486
17606
|
if (!plugins || typeof plugins !== "object") return null;
|
|
17487
17607
|
const here = realpathOr(repoRoot());
|
|
17488
17608
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -17492,7 +17612,7 @@ function registeredVerityPlugin() {
|
|
|
17492
17612
|
for (const entry of Array.isArray(value) ? value : []) {
|
|
17493
17613
|
const e = entry;
|
|
17494
17614
|
const installPath = typeof e.installPath === "string" ? e.installPath : "";
|
|
17495
|
-
if (!installPath || !(0,
|
|
17615
|
+
if (!installPath || !(0, import_node_fs9.existsSync)(installPath)) continue;
|
|
17496
17616
|
if (!entryAppliesHere(entry, here)) continue;
|
|
17497
17617
|
return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
|
|
17498
17618
|
}
|
|
@@ -17544,28 +17664,28 @@ async function resolveHookWiring() {
|
|
|
17544
17664
|
}
|
|
17545
17665
|
|
|
17546
17666
|
// src/lib/cli-provenance.ts
|
|
17547
|
-
var
|
|
17667
|
+
var import_node_fs10 = require("node:fs");
|
|
17548
17668
|
var import_node_os3 = require("node:os");
|
|
17549
|
-
var
|
|
17669
|
+
var import_node_path11 = require("node:path");
|
|
17550
17670
|
var CLI_PACKAGE = "@codacy/verity-cli";
|
|
17551
|
-
var CLI_ENTRY = (0,
|
|
17671
|
+
var CLI_ENTRY = (0, import_node_path11.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
|
|
17552
17672
|
function readJson(path) {
|
|
17553
17673
|
try {
|
|
17554
|
-
const parsed = JSON.parse((0,
|
|
17674
|
+
const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
|
|
17555
17675
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
17556
17676
|
} catch {
|
|
17557
17677
|
return null;
|
|
17558
17678
|
}
|
|
17559
17679
|
}
|
|
17560
17680
|
function versionUnder(base) {
|
|
17561
|
-
const entry = (0,
|
|
17562
|
-
if (!(0,
|
|
17563
|
-
const pkg = readJson((0,
|
|
17681
|
+
const entry = (0, import_node_path11.join)(base, CLI_ENTRY);
|
|
17682
|
+
if (!(0, import_node_fs10.existsSync)(entry)) return null;
|
|
17683
|
+
const pkg = readJson((0, import_node_path11.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
|
|
17564
17684
|
return typeof pkg?.version === "string" ? pkg.version : null;
|
|
17565
17685
|
}
|
|
17566
17686
|
function versionForEntry(entry) {
|
|
17567
17687
|
try {
|
|
17568
|
-
const pkg = readJson((0,
|
|
17688
|
+
const pkg = readJson((0, import_node_path11.join)((0, import_node_path11.dirname)((0, import_node_fs10.realpathSync)(entry)), "..", "package.json"));
|
|
17569
17689
|
return typeof pkg?.version === "string" ? pkg.version : null;
|
|
17570
17690
|
} catch {
|
|
17571
17691
|
return null;
|
|
@@ -17573,16 +17693,16 @@ function versionForEntry(entry) {
|
|
|
17573
17693
|
}
|
|
17574
17694
|
function resolveHooksCli(pluginRoot) {
|
|
17575
17695
|
const override = process.env.VERITY_CLI_PATH;
|
|
17576
|
-
if (override && (0,
|
|
17696
|
+
if (override && (0, import_node_fs10.existsSync)(override)) {
|
|
17577
17697
|
return { version: versionForEntry(override), rung: "override" };
|
|
17578
17698
|
}
|
|
17579
17699
|
const fromPlugin = versionUnder(pluginRoot);
|
|
17580
17700
|
if (fromPlugin !== null) return { version: fromPlugin, rung: "plugin" };
|
|
17581
|
-
if ((0,
|
|
17582
|
-
const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0,
|
|
17701
|
+
if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
|
|
17702
|
+
const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path11.join)((0, import_node_os3.homedir)(), ".verity", "plugin-cli");
|
|
17583
17703
|
const fromData = versionUnder(dataDir);
|
|
17584
17704
|
if (fromData !== null) return { version: fromData, rung: "plugin-data" };
|
|
17585
|
-
if ((0,
|
|
17705
|
+
if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
|
|
17586
17706
|
const global = globalVerityVersion();
|
|
17587
17707
|
if (global !== null) return { version: global, rung: "global" };
|
|
17588
17708
|
return null;
|
|
@@ -17684,7 +17804,7 @@ function pluginCliInvocation() {
|
|
|
17684
17804
|
return resolverCommand(root);
|
|
17685
17805
|
}
|
|
17686
17806
|
function resolverCommand(root) {
|
|
17687
|
-
return `node ${JSON.stringify((0,
|
|
17807
|
+
return `node ${JSON.stringify((0, import_node_path11.join)(root, "scripts", "verity.mjs"))}`;
|
|
17688
17808
|
}
|
|
17689
17809
|
|
|
17690
17810
|
// src/commands/hooks.ts
|
|
@@ -17824,8 +17944,8 @@ var import_node_crypto9 = require("node:crypto");
|
|
|
17824
17944
|
|
|
17825
17945
|
// src/lib/conversation-buffer.ts
|
|
17826
17946
|
var import_promises5 = require("node:fs/promises");
|
|
17827
|
-
var
|
|
17828
|
-
var
|
|
17947
|
+
var import_node_fs11 = require("node:fs");
|
|
17948
|
+
var import_node_child_process6 = require("node:child_process");
|
|
17829
17949
|
var import_node_crypto = require("node:crypto");
|
|
17830
17950
|
function stripImageReferences(text) {
|
|
17831
17951
|
return text.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
|
|
@@ -17860,7 +17980,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
|
|
|
17860
17980
|
}
|
|
17861
17981
|
async function readAndClearConversationBuffer(currentSessionId) {
|
|
17862
17982
|
try {
|
|
17863
|
-
if ((0,
|
|
17983
|
+
if ((0, import_node_fs11.existsSync)(CONVERSATION_BUFFER_FILE)) {
|
|
17864
17984
|
const entries = await readBufferEntries();
|
|
17865
17985
|
let mine = entries;
|
|
17866
17986
|
let others = [];
|
|
@@ -17884,7 +18004,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
|
|
|
17884
18004
|
};
|
|
17885
18005
|
}
|
|
17886
18006
|
}
|
|
17887
|
-
if ((0,
|
|
18007
|
+
if ((0, import_node_fs11.existsSync)(INTENT_FILE)) {
|
|
17888
18008
|
try {
|
|
17889
18009
|
const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
|
|
17890
18010
|
await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
|
|
@@ -17928,7 +18048,7 @@ async function readBufferEntries() {
|
|
|
17928
18048
|
}
|
|
17929
18049
|
function getRecentCommitMessages() {
|
|
17930
18050
|
try {
|
|
17931
|
-
const output = (0,
|
|
18051
|
+
const output = (0, import_node_child_process6.execSync)(
|
|
17932
18052
|
'git log --since="30 minutes ago" --format="%s" -5',
|
|
17933
18053
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
17934
18054
|
).trim();
|
|
@@ -18177,9 +18297,9 @@ function isCommandOnlyTurn(input) {
|
|
|
18177
18297
|
|
|
18178
18298
|
// src/lib/context-identity.ts
|
|
18179
18299
|
var import_node_crypto2 = require("node:crypto");
|
|
18180
|
-
var
|
|
18300
|
+
var import_node_fs12 = require("node:fs");
|
|
18181
18301
|
var import_node_os4 = require("node:os");
|
|
18182
|
-
var
|
|
18302
|
+
var import_node_path12 = require("node:path");
|
|
18183
18303
|
var SHARED_SENTINELS = /* @__PURE__ */ new Set([
|
|
18184
18304
|
"",
|
|
18185
18305
|
"-",
|
|
@@ -18217,7 +18337,7 @@ function contextIdentity(input) {
|
|
|
18217
18337
|
if (rawTree && !isSharedSentinel(rawTree)) {
|
|
18218
18338
|
let resolved = rawTree;
|
|
18219
18339
|
try {
|
|
18220
|
-
resolved =
|
|
18340
|
+
resolved = import_node_fs12.realpathSync.native(rawTree);
|
|
18221
18341
|
} catch {
|
|
18222
18342
|
}
|
|
18223
18343
|
treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
@@ -18233,13 +18353,13 @@ function contextIdentity(input) {
|
|
|
18233
18353
|
}
|
|
18234
18354
|
function verityHome() {
|
|
18235
18355
|
const override = process.env.VERITY_HOME;
|
|
18236
|
-
return override && override.trim() ? (0,
|
|
18356
|
+
return override && override.trim() ? (0, import_node_path12.resolve)(override) : (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".verity");
|
|
18237
18357
|
}
|
|
18238
18358
|
function dossierDir(identity) {
|
|
18239
|
-
return (0,
|
|
18359
|
+
return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
|
|
18240
18360
|
}
|
|
18241
18361
|
function treeDir(identity) {
|
|
18242
|
-
return (0,
|
|
18362
|
+
return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
|
|
18243
18363
|
}
|
|
18244
18364
|
function scopeIdentity(token, sessionId) {
|
|
18245
18365
|
const t = (token ?? "").trim();
|
|
@@ -18254,8 +18374,8 @@ function sessionScopeKey(token, sessionId) {
|
|
|
18254
18374
|
|
|
18255
18375
|
// src/lib/task-context-buffer.ts
|
|
18256
18376
|
var import_promises6 = require("node:fs/promises");
|
|
18257
|
-
var
|
|
18258
|
-
var
|
|
18377
|
+
var import_node_fs13 = require("node:fs");
|
|
18378
|
+
var import_node_path13 = require("node:path");
|
|
18259
18379
|
var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
|
|
18260
18380
|
var MAX_BUFFER_BYTES = 500 * 1024;
|
|
18261
18381
|
var MAX_PROMPT_CHARS = 2e3;
|
|
@@ -18294,7 +18414,7 @@ async function appendResponseToTaskBuffer(taskId, assistantResponse, actionSumma
|
|
|
18294
18414
|
}
|
|
18295
18415
|
async function readTaskContextBuffer(taskId) {
|
|
18296
18416
|
const filePath = bufferPath(taskId);
|
|
18297
|
-
if (!(0,
|
|
18417
|
+
if (!(0, import_node_fs13.existsSync)(filePath)) return null;
|
|
18298
18418
|
try {
|
|
18299
18419
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
18300
18420
|
if (!content.trim()) return null;
|
|
@@ -18328,12 +18448,12 @@ async function readTaskContextBuffer(taskId) {
|
|
|
18328
18448
|
}
|
|
18329
18449
|
async function cleanupTaskContextBuffers() {
|
|
18330
18450
|
try {
|
|
18331
|
-
if (!(0,
|
|
18451
|
+
if (!(0, import_node_fs13.existsSync)(TASK_CONTEXT_DIR)) return;
|
|
18332
18452
|
const files = await (0, import_promises6.readdir)(TASK_CONTEXT_DIR);
|
|
18333
18453
|
const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
18334
18454
|
for (const file of files) {
|
|
18335
18455
|
if (!file.endsWith(".jsonl")) continue;
|
|
18336
|
-
const filePath = (0,
|
|
18456
|
+
const filePath = (0, import_node_path13.join)(TASK_CONTEXT_DIR, file);
|
|
18337
18457
|
try {
|
|
18338
18458
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
18339
18459
|
if (stats.mtimeMs < cutoffMs) {
|
|
@@ -18347,13 +18467,13 @@ async function cleanupTaskContextBuffers() {
|
|
|
18347
18467
|
}
|
|
18348
18468
|
function bufferPath(taskId) {
|
|
18349
18469
|
const safe = taskId.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
18350
|
-
return (0,
|
|
18470
|
+
return (0, import_node_path13.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
|
|
18351
18471
|
}
|
|
18352
18472
|
async function appendEntry(taskId, entry) {
|
|
18353
18473
|
try {
|
|
18354
18474
|
await (0, import_promises6.mkdir)(TASK_CONTEXT_DIR, { recursive: true });
|
|
18355
18475
|
const filePath = bufferPath(taskId);
|
|
18356
|
-
if ((0,
|
|
18476
|
+
if ((0, import_node_fs13.existsSync)(filePath)) {
|
|
18357
18477
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
18358
18478
|
if (stats.size >= MAX_BUFFER_BYTES) {
|
|
18359
18479
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
@@ -18364,7 +18484,7 @@ async function appendEntry(taskId, entry) {
|
|
|
18364
18484
|
}
|
|
18365
18485
|
}
|
|
18366
18486
|
const line2 = JSON.stringify(entry) + "\n";
|
|
18367
|
-
const existing = (0,
|
|
18487
|
+
const existing = (0, import_node_fs13.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
|
|
18368
18488
|
await (0, import_promises6.writeFile)(filePath, existing + line2);
|
|
18369
18489
|
} catch {
|
|
18370
18490
|
}
|
|
@@ -18372,20 +18492,20 @@ async function appendEntry(taskId, entry) {
|
|
|
18372
18492
|
|
|
18373
18493
|
// src/lib/memory-retrieval.ts
|
|
18374
18494
|
var import_promises8 = require("node:fs/promises");
|
|
18375
|
-
var
|
|
18376
|
-
var
|
|
18495
|
+
var import_node_fs16 = require("node:fs");
|
|
18496
|
+
var import_node_path16 = require("node:path");
|
|
18377
18497
|
|
|
18378
18498
|
// src/lib/org-mirror.ts
|
|
18379
|
-
var
|
|
18499
|
+
var import_node_fs14 = require("node:fs");
|
|
18380
18500
|
var import_promises7 = require("node:fs/promises");
|
|
18381
|
-
var
|
|
18501
|
+
var import_node_path14 = require("node:path");
|
|
18382
18502
|
var ORG_KINDS = ["decision", "security", "gotcha", "pattern", "domain", "integration"];
|
|
18383
18503
|
var STATE_FILE = ".org-pull-state.json";
|
|
18384
18504
|
var BODY_MAX = 8192;
|
|
18385
18505
|
function orgMirrorDir(remote = requestRemote()) {
|
|
18386
18506
|
const parsed = parseRemote(remote);
|
|
18387
18507
|
if (!parsed) return null;
|
|
18388
|
-
return (0,
|
|
18508
|
+
return (0, import_node_path14.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
|
|
18389
18509
|
}
|
|
18390
18510
|
function slugify(s) {
|
|
18391
18511
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
@@ -18451,7 +18571,7 @@ function parseOrgNode(content) {
|
|
|
18451
18571
|
}
|
|
18452
18572
|
async function readState(dir) {
|
|
18453
18573
|
try {
|
|
18454
|
-
const parsed = JSON.parse(await (0, import_promises7.readFile)((0,
|
|
18574
|
+
const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path14.join)(dir, STATE_FILE), "utf-8"));
|
|
18455
18575
|
return {
|
|
18456
18576
|
version: typeof parsed?.version === "string" ? parsed.version : null,
|
|
18457
18577
|
organization: parsed?.organization && typeof parsed.organization.id === "string" ? parsed.organization : null,
|
|
@@ -18463,7 +18583,7 @@ async function readState(dir) {
|
|
|
18463
18583
|
}
|
|
18464
18584
|
async function writeState(dir, state) {
|
|
18465
18585
|
await (0, import_promises7.mkdir)(dir, { recursive: true });
|
|
18466
|
-
await (0, import_promises7.writeFile)((0,
|
|
18586
|
+
await (0, import_promises7.writeFile)((0, import_node_path14.join)(dir, STATE_FILE), JSON.stringify({
|
|
18467
18587
|
...state.version ? { version: state.version } : {},
|
|
18468
18588
|
organization: state.organization,
|
|
18469
18589
|
pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -18528,24 +18648,24 @@ async function pullOrgKnowledge(opts) {
|
|
|
18528
18648
|
for (const n of nodes) {
|
|
18529
18649
|
const rel = orgNodePath(n);
|
|
18530
18650
|
if (written.has(rel)) continue;
|
|
18531
|
-
await (0, import_promises7.mkdir)((0,
|
|
18532
|
-
await (0, import_promises7.writeFile)((0,
|
|
18651
|
+
await (0, import_promises7.mkdir)((0, import_node_path14.join)(dir, rel.split("/")[0]), { recursive: true });
|
|
18652
|
+
await (0, import_promises7.writeFile)((0, import_node_path14.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
|
|
18533
18653
|
written.add(rel);
|
|
18534
18654
|
}
|
|
18535
18655
|
for (const rel of state.files) {
|
|
18536
|
-
if (!written.has(rel)) await (0, import_promises7.rm)((0,
|
|
18656
|
+
if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path14.join)(dir, rel), { force: true });
|
|
18537
18657
|
}
|
|
18538
|
-
await (0, import_promises7.writeFile)((0,
|
|
18658
|
+
await (0, import_promises7.writeFile)((0, import_node_path14.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
|
|
18539
18659
|
await writeState(dir, { version: org ? page.version : null, organization: org, files: [...written].sort() });
|
|
18540
18660
|
return { ok: true, status: org ? "pulled" : "none", received: nodes.length, dir };
|
|
18541
18661
|
}
|
|
18542
18662
|
async function readOrgMirror(remote = requestRemote()) {
|
|
18543
18663
|
const dir = orgMirrorDir(remote);
|
|
18544
|
-
if (!dir || !(0,
|
|
18664
|
+
if (!dir || !(0, import_node_fs14.existsSync)(dir)) return [];
|
|
18545
18665
|
const out2 = [];
|
|
18546
18666
|
for (const kind of ORG_KINDS) {
|
|
18547
|
-
const kindDir = (0,
|
|
18548
|
-
if (!(0,
|
|
18667
|
+
const kindDir = (0, import_node_path14.join)(dir, kind);
|
|
18668
|
+
if (!(0, import_node_fs14.existsSync)(kindDir)) continue;
|
|
18549
18669
|
let files;
|
|
18550
18670
|
try {
|
|
18551
18671
|
files = await (0, import_promises7.readdir)(kindDir);
|
|
@@ -18555,7 +18675,7 @@ async function readOrgMirror(remote = requestRemote()) {
|
|
|
18555
18675
|
for (const file of files) {
|
|
18556
18676
|
if (!file.endsWith(".md")) continue;
|
|
18557
18677
|
try {
|
|
18558
|
-
const node = parseOrgNode(await (0, import_promises7.readFile)((0,
|
|
18678
|
+
const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path14.join)(kindDir, file), "utf-8"));
|
|
18559
18679
|
if (node) out2.push(node);
|
|
18560
18680
|
} catch {
|
|
18561
18681
|
}
|
|
@@ -18565,29 +18685,29 @@ async function readOrgMirror(remote = requestRemote()) {
|
|
|
18565
18685
|
}
|
|
18566
18686
|
|
|
18567
18687
|
// src/lib/safe-read.ts
|
|
18568
|
-
var
|
|
18569
|
-
var
|
|
18570
|
-
var FLAGS =
|
|
18688
|
+
var import_node_fs15 = require("node:fs");
|
|
18689
|
+
var import_node_path15 = require("node:path");
|
|
18690
|
+
var FLAGS = import_node_fs15.constants;
|
|
18571
18691
|
var NOFOLLOW = FLAGS.O_NOFOLLOW;
|
|
18572
18692
|
var NONBLOCK = FLAGS.O_NONBLOCK;
|
|
18573
18693
|
function closeOpened(fd) {
|
|
18574
18694
|
try {
|
|
18575
|
-
(0,
|
|
18695
|
+
(0, import_node_fs15.closeSync)(fd);
|
|
18576
18696
|
} catch {
|
|
18577
18697
|
}
|
|
18578
18698
|
}
|
|
18579
18699
|
function isInsideRoot(realRoot, realPath) {
|
|
18580
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
18700
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path15.sep) ? realRoot : realRoot + import_node_path15.sep);
|
|
18581
18701
|
}
|
|
18582
18702
|
function sameOpenedFile(opened, current, nofollowAvailable) {
|
|
18583
18703
|
if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
|
|
18584
18704
|
return opened.ino === current.ino && opened.dev === current.dev;
|
|
18585
18705
|
}
|
|
18586
18706
|
function openRegularInRoot(root, path) {
|
|
18587
|
-
const full = (0,
|
|
18707
|
+
const full = (0, import_node_path15.isAbsolute)(path) ? path : (0, import_node_path15.join)(root, path);
|
|
18588
18708
|
let fd;
|
|
18589
18709
|
try {
|
|
18590
|
-
fd = (0,
|
|
18710
|
+
fd = (0, import_node_fs15.openSync)(full, import_node_fs15.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
|
|
18591
18711
|
} catch (err2) {
|
|
18592
18712
|
const code = err2.code;
|
|
18593
18713
|
if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
|
|
@@ -18595,18 +18715,18 @@ function openRegularInRoot(root, path) {
|
|
|
18595
18715
|
return { ok: false, reason: "unreadable" };
|
|
18596
18716
|
}
|
|
18597
18717
|
try {
|
|
18598
|
-
const opened = (0,
|
|
18718
|
+
const opened = (0, import_node_fs15.fstatSync)(fd, { bigint: true });
|
|
18599
18719
|
if (!opened.isFile()) {
|
|
18600
18720
|
closeOpened(fd);
|
|
18601
18721
|
return { ok: false, reason: "not-regular" };
|
|
18602
18722
|
}
|
|
18603
|
-
const realRoot =
|
|
18604
|
-
const realPath =
|
|
18723
|
+
const realRoot = import_node_fs15.realpathSync.native(root);
|
|
18724
|
+
const realPath = import_node_fs15.realpathSync.native(full);
|
|
18605
18725
|
if (!isInsideRoot(realRoot, realPath)) {
|
|
18606
18726
|
closeOpened(fd);
|
|
18607
18727
|
return { ok: false, reason: "outside-root" };
|
|
18608
18728
|
}
|
|
18609
|
-
const current = (0,
|
|
18729
|
+
const current = (0, import_node_fs15.statSync)(realPath, { bigint: true });
|
|
18610
18730
|
if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
|
|
18611
18731
|
closeOpened(fd);
|
|
18612
18732
|
return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
|
|
@@ -18628,7 +18748,7 @@ function readOpened(fd, size) {
|
|
|
18628
18748
|
const buffer = Buffer.alloc(size);
|
|
18629
18749
|
let offset = 0;
|
|
18630
18750
|
while (offset < size) {
|
|
18631
|
-
const n = (0,
|
|
18751
|
+
const n = (0, import_node_fs15.readSync)(fd, buffer, offset, size - offset, offset);
|
|
18632
18752
|
if (n === 0) break;
|
|
18633
18753
|
offset += n;
|
|
18634
18754
|
}
|
|
@@ -18943,14 +19063,14 @@ function parseFrontmatter(content) {
|
|
|
18943
19063
|
return { fm, body: match[2].trim() };
|
|
18944
19064
|
}
|
|
18945
19065
|
async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
|
|
18946
|
-
const hasRepoGraph = (0,
|
|
19066
|
+
const hasRepoGraph = (0, import_node_fs16.existsSync)(memoryDir());
|
|
18947
19067
|
const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
|
|
18948
19068
|
const promptTokens = tokenize(promptText);
|
|
18949
19069
|
const orgPromptTerms = orgTerms(promptText);
|
|
18950
19070
|
const nodes = [];
|
|
18951
19071
|
for (const domain of hasRepoGraph ? DOMAINS : []) {
|
|
18952
|
-
const domainDir = (0,
|
|
18953
|
-
if (!(0,
|
|
19072
|
+
const domainDir = (0, import_node_path16.join)(memoryDir(), domain);
|
|
19073
|
+
if (!(0, import_node_fs16.existsSync)(domainDir)) continue;
|
|
18954
19074
|
try {
|
|
18955
19075
|
const files = await (0, import_promises8.readdir)(domainDir);
|
|
18956
19076
|
for (const file of files) {
|
|
@@ -19024,27 +19144,27 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
19024
19144
|
}
|
|
19025
19145
|
|
|
19026
19146
|
// src/lib/injection-record.ts
|
|
19027
|
-
var
|
|
19147
|
+
var import_node_fs18 = require("node:fs");
|
|
19028
19148
|
var import_node_crypto3 = require("node:crypto");
|
|
19029
19149
|
|
|
19030
19150
|
// src/lib/safe-write.ts
|
|
19031
|
-
var
|
|
19032
|
-
var
|
|
19033
|
-
var FLAGS2 =
|
|
19151
|
+
var import_node_fs17 = require("node:fs");
|
|
19152
|
+
var import_node_path17 = require("node:path");
|
|
19153
|
+
var FLAGS2 = import_node_fs17.constants;
|
|
19034
19154
|
var O_NOFOLLOW = FLAGS2.O_NOFOLLOW ?? 0;
|
|
19035
19155
|
var NOFOLLOW_AVAILABLE = O_NOFOLLOW !== 0;
|
|
19036
19156
|
function validateRoot(root) {
|
|
19037
19157
|
try {
|
|
19038
|
-
const parentReal = (0,
|
|
19039
|
-
const expected = (0,
|
|
19158
|
+
const parentReal = (0, import_node_fs17.realpathSync)((0, import_node_path17.dirname)(root));
|
|
19159
|
+
const expected = (0, import_node_path17.join)(parentReal, (0, import_node_path17.basename)(root));
|
|
19040
19160
|
try {
|
|
19041
|
-
(0,
|
|
19161
|
+
(0, import_node_fs17.mkdirSync)(expected);
|
|
19042
19162
|
} catch (e) {
|
|
19043
19163
|
if (e.code !== "EEXIST") return null;
|
|
19044
19164
|
}
|
|
19045
|
-
const st = (0,
|
|
19165
|
+
const st = (0, import_node_fs17.lstatSync)(expected, { bigint: true });
|
|
19046
19166
|
if (st.isSymbolicLink() || !st.isDirectory()) return null;
|
|
19047
|
-
if ((0,
|
|
19167
|
+
if ((0, import_node_fs17.realpathSync)(expected) !== expected) return null;
|
|
19048
19168
|
return { real: expected, dev: st.dev, ino: st.ino };
|
|
19049
19169
|
} catch {
|
|
19050
19170
|
return null;
|
|
@@ -19052,18 +19172,18 @@ function validateRoot(root) {
|
|
|
19052
19172
|
}
|
|
19053
19173
|
function rootUnchanged(root) {
|
|
19054
19174
|
try {
|
|
19055
|
-
const st = (0,
|
|
19175
|
+
const st = (0, import_node_fs17.lstatSync)(root.real, { bigint: true });
|
|
19056
19176
|
return !st.isSymbolicLink() && st.isDirectory() && st.dev === root.dev && st.ino === root.ino;
|
|
19057
19177
|
} catch {
|
|
19058
19178
|
return false;
|
|
19059
19179
|
}
|
|
19060
19180
|
}
|
|
19061
19181
|
function bareName(name2) {
|
|
19062
|
-
return !!name2 && name2 === (0,
|
|
19182
|
+
return !!name2 && name2 === (0, import_node_path17.basename)(name2) && name2 !== "." && name2 !== ".." && !name2.includes("\0");
|
|
19063
19183
|
}
|
|
19064
19184
|
function absentOrRegular(path) {
|
|
19065
19185
|
try {
|
|
19066
|
-
const st = (0,
|
|
19186
|
+
const st = (0, import_node_fs17.lstatSync)(path);
|
|
19067
19187
|
return st.isFile() && !st.isSymbolicLink();
|
|
19068
19188
|
} catch (e) {
|
|
19069
19189
|
return e.code === "ENOENT";
|
|
@@ -19071,11 +19191,11 @@ function absentOrRegular(path) {
|
|
|
19071
19191
|
}
|
|
19072
19192
|
function verifyOpened(fd, path, root) {
|
|
19073
19193
|
try {
|
|
19074
|
-
const opened = (0,
|
|
19194
|
+
const opened = (0, import_node_fs17.fstatSync)(fd, { bigint: true });
|
|
19075
19195
|
if (!opened.isFile() || opened.nlink !== 1n) return false;
|
|
19076
|
-
const real = (0,
|
|
19196
|
+
const real = (0, import_node_fs17.realpathSync)(path);
|
|
19077
19197
|
if (!isInsideRoot(root.real, real)) return false;
|
|
19078
|
-
const current = (0,
|
|
19198
|
+
const current = (0, import_node_fs17.statSync)(real, { bigint: true });
|
|
19079
19199
|
if (!sameOpenedFile(opened, current, NOFOLLOW_AVAILABLE)) return false;
|
|
19080
19200
|
return rootUnchanged(root);
|
|
19081
19201
|
} catch {
|
|
@@ -19084,21 +19204,21 @@ function verifyOpened(fd, path, root) {
|
|
|
19084
19204
|
}
|
|
19085
19205
|
function removeIfOurs(fd, path) {
|
|
19086
19206
|
try {
|
|
19087
|
-
const opened = (0,
|
|
19088
|
-
const at = (0,
|
|
19089
|
-
if (!at.isSymbolicLink() && at.dev === opened.dev && at.ino === opened.ino) (0,
|
|
19207
|
+
const opened = (0, import_node_fs17.fstatSync)(fd, { bigint: true });
|
|
19208
|
+
const at = (0, import_node_fs17.lstatSync)(path, { bigint: true });
|
|
19209
|
+
if (!at.isSymbolicLink() && at.dev === opened.dev && at.ino === opened.ino) (0, import_node_fs17.unlinkSync)(path);
|
|
19090
19210
|
} catch {
|
|
19091
19211
|
}
|
|
19092
19212
|
}
|
|
19093
19213
|
function openTarget(path, append2) {
|
|
19094
|
-
const base =
|
|
19214
|
+
const base = import_node_fs17.constants.O_WRONLY | (append2 ? import_node_fs17.constants.O_APPEND : 0) | O_NOFOLLOW;
|
|
19095
19215
|
try {
|
|
19096
|
-
return { fd: (0,
|
|
19216
|
+
return { fd: (0, import_node_fs17.openSync)(path, base), created: false };
|
|
19097
19217
|
} catch (e) {
|
|
19098
19218
|
if (e.code !== "ENOENT") return null;
|
|
19099
19219
|
}
|
|
19100
19220
|
try {
|
|
19101
|
-
return { fd: (0,
|
|
19221
|
+
return { fd: (0, import_node_fs17.openSync)(path, base | import_node_fs17.constants.O_CREAT | import_node_fs17.constants.O_EXCL, 384), created: true };
|
|
19102
19222
|
} catch {
|
|
19103
19223
|
return null;
|
|
19104
19224
|
}
|
|
@@ -19106,7 +19226,7 @@ function openTarget(path, append2) {
|
|
|
19106
19226
|
function writeVerified(root, name2, hooks, append2, write) {
|
|
19107
19227
|
const r = validateRoot(root);
|
|
19108
19228
|
if (!r || !bareName(name2)) return false;
|
|
19109
|
-
const path = (0,
|
|
19229
|
+
const path = (0, import_node_path17.join)(r.real, name2);
|
|
19110
19230
|
if (!absentOrRegular(path)) return false;
|
|
19111
19231
|
if (!runHook(hooks)) return false;
|
|
19112
19232
|
const opened = openTarget(path, append2);
|
|
@@ -19122,7 +19242,7 @@ function writeVerified(root, name2, hooks, append2, write) {
|
|
|
19122
19242
|
return false;
|
|
19123
19243
|
} finally {
|
|
19124
19244
|
try {
|
|
19125
|
-
(0,
|
|
19245
|
+
(0, import_node_fs17.closeSync)(opened.fd);
|
|
19126
19246
|
} catch {
|
|
19127
19247
|
}
|
|
19128
19248
|
}
|
|
@@ -19137,13 +19257,13 @@ function runHook(hooks) {
|
|
|
19137
19257
|
}
|
|
19138
19258
|
function appendInRoot(root, name2, text, hooks = {}) {
|
|
19139
19259
|
return writeVerified(root, name2, hooks, true, (fd) => {
|
|
19140
|
-
(0,
|
|
19260
|
+
(0, import_node_fs17.writeSync)(fd, text);
|
|
19141
19261
|
});
|
|
19142
19262
|
}
|
|
19143
19263
|
function replaceInRoot(root, name2, text, hooks = {}) {
|
|
19144
19264
|
return writeVerified(root, name2, hooks, false, (fd) => {
|
|
19145
|
-
(0,
|
|
19146
|
-
(0,
|
|
19265
|
+
(0, import_node_fs17.ftruncateSync)(fd, 0);
|
|
19266
|
+
(0, import_node_fs17.writeSync)(fd, text, 0);
|
|
19147
19267
|
});
|
|
19148
19268
|
}
|
|
19149
19269
|
|
|
@@ -19191,7 +19311,7 @@ function hashPrompt(prompt) {
|
|
|
19191
19311
|
function recordInjection(event) {
|
|
19192
19312
|
if (!appendInRoot(projectPath(VERITY_DIR), "injections.jsonl", JSON.stringify(event) + "\n")) return;
|
|
19193
19313
|
try {
|
|
19194
|
-
if ((0,
|
|
19314
|
+
if ((0, import_node_fs18.lstatSync)(recordPath()).size > COMPACT_AT_BYTES) writeEvents(readPendingInjections());
|
|
19195
19315
|
} catch {
|
|
19196
19316
|
}
|
|
19197
19317
|
}
|
|
@@ -19201,7 +19321,7 @@ function writeEvents(events) {
|
|
|
19201
19321
|
function readPendingInjections() {
|
|
19202
19322
|
try {
|
|
19203
19323
|
const p = recordPath();
|
|
19204
|
-
if (!(0,
|
|
19324
|
+
if (!(0, import_node_fs18.existsSync)(p)) return [];
|
|
19205
19325
|
const read2 = readRegularFileInRoot(projectPath(VERITY_DIR), "injections.jsonl", MAX_RECORD_BYTES);
|
|
19206
19326
|
if (!read2.ok) return [];
|
|
19207
19327
|
const out2 = [];
|
|
@@ -19221,13 +19341,13 @@ function readPendingInjections() {
|
|
|
19221
19341
|
|
|
19222
19342
|
// src/lib/memory-sync.ts
|
|
19223
19343
|
var import_promises9 = require("node:fs/promises");
|
|
19224
|
-
var
|
|
19225
|
-
var
|
|
19344
|
+
var import_node_fs21 = require("node:fs");
|
|
19345
|
+
var import_node_path19 = require("node:path");
|
|
19226
19346
|
var import_node_crypto4 = require("node:crypto");
|
|
19227
19347
|
|
|
19228
19348
|
// src/lib/gitignore.ts
|
|
19229
|
-
var
|
|
19230
|
-
var
|
|
19349
|
+
var import_node_child_process7 = require("node:child_process");
|
|
19350
|
+
var import_node_fs19 = require("node:fs");
|
|
19231
19351
|
var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
|
|
19232
19352
|
var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
|
|
19233
19353
|
var VERITY_GITIGNORE_BLOCK = [
|
|
@@ -19263,7 +19383,7 @@ var SUPERSEDED_MEMORY_LINES = /* @__PURE__ */ new Set([
|
|
|
19263
19383
|
]);
|
|
19264
19384
|
function isIgnored(path) {
|
|
19265
19385
|
try {
|
|
19266
|
-
(0,
|
|
19386
|
+
(0, import_node_child_process7.execSync)(`git check-ignore -q -- "${path}"`, { stdio: "pipe" });
|
|
19267
19387
|
return true;
|
|
19268
19388
|
} catch (err2) {
|
|
19269
19389
|
return err2.status === 1 ? false : null;
|
|
@@ -19283,7 +19403,7 @@ function memoryPosture() {
|
|
|
19283
19403
|
}
|
|
19284
19404
|
function committedMemoryFiles() {
|
|
19285
19405
|
try {
|
|
19286
|
-
return (0,
|
|
19406
|
+
return (0, import_node_child_process7.execSync)("git ls-files -z -- .verity/memory", {
|
|
19287
19407
|
encoding: "utf-8",
|
|
19288
19408
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19289
19409
|
}).split("\0").filter(Boolean);
|
|
@@ -19311,7 +19431,7 @@ function fenceMemoryLines(lines) {
|
|
|
19311
19431
|
function ensureVerityGitignore() {
|
|
19312
19432
|
let content = "";
|
|
19313
19433
|
try {
|
|
19314
|
-
content = (0,
|
|
19434
|
+
content = (0, import_node_fs19.readFileSync)(".gitignore", "utf-8");
|
|
19315
19435
|
} catch {
|
|
19316
19436
|
}
|
|
19317
19437
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -19338,7 +19458,7 @@ function ensureVerityGitignore() {
|
|
|
19338
19458
|
const sep5 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
19339
19459
|
text = text + sep5 + VERITY_GITIGNORE_BLOCK;
|
|
19340
19460
|
}
|
|
19341
|
-
if (text !== content) (0,
|
|
19461
|
+
if (text !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text);
|
|
19342
19462
|
return verified(
|
|
19343
19463
|
memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
|
|
19344
19464
|
);
|
|
@@ -19349,7 +19469,7 @@ function ensureVerityGitignore() {
|
|
|
19349
19469
|
function untrackMemory() {
|
|
19350
19470
|
if (committedMemoryFiles().length === 0) return "none";
|
|
19351
19471
|
try {
|
|
19352
|
-
(0,
|
|
19472
|
+
(0, import_node_child_process7.execSync)("git rm -r --cached --quiet -- .verity/memory", { stdio: "pipe" });
|
|
19353
19473
|
return "untracked";
|
|
19354
19474
|
} catch {
|
|
19355
19475
|
return "failed";
|
|
@@ -19358,7 +19478,7 @@ function untrackMemory() {
|
|
|
19358
19478
|
function writeFencedBlock() {
|
|
19359
19479
|
let content = "";
|
|
19360
19480
|
try {
|
|
19361
|
-
content = (0,
|
|
19481
|
+
content = (0, import_node_fs19.readFileSync)(".gitignore", "utf-8");
|
|
19362
19482
|
} catch {
|
|
19363
19483
|
}
|
|
19364
19484
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -19370,7 +19490,7 @@ function writeFencedBlock() {
|
|
|
19370
19490
|
text = text + sep5 + VERITY_GITIGNORE_BLOCK;
|
|
19371
19491
|
}
|
|
19372
19492
|
try {
|
|
19373
|
-
(0,
|
|
19493
|
+
(0, import_node_fs19.writeFileSync)(".gitignore", text);
|
|
19374
19494
|
return true;
|
|
19375
19495
|
} catch {
|
|
19376
19496
|
return false;
|
|
@@ -19379,14 +19499,14 @@ function writeFencedBlock() {
|
|
|
19379
19499
|
function fenceMemory() {
|
|
19380
19500
|
let original = null;
|
|
19381
19501
|
try {
|
|
19382
|
-
original = (0,
|
|
19502
|
+
original = (0, import_node_fs19.readFileSync)(".gitignore", "utf-8");
|
|
19383
19503
|
} catch {
|
|
19384
19504
|
original = null;
|
|
19385
19505
|
}
|
|
19386
19506
|
const restore = () => {
|
|
19387
19507
|
try {
|
|
19388
|
-
if (original === null) (0,
|
|
19389
|
-
else (0,
|
|
19508
|
+
if (original === null) (0, import_node_fs19.rmSync)(".gitignore", { force: true });
|
|
19509
|
+
else (0, import_node_fs19.writeFileSync)(".gitignore", original);
|
|
19390
19510
|
} catch {
|
|
19391
19511
|
}
|
|
19392
19512
|
};
|
|
@@ -19404,7 +19524,7 @@ function fenceMemory() {
|
|
|
19404
19524
|
}
|
|
19405
19525
|
function memoryOptOut() {
|
|
19406
19526
|
try {
|
|
19407
|
-
return (0,
|
|
19527
|
+
return (0, import_node_fs19.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
|
|
19408
19528
|
} catch {
|
|
19409
19529
|
return false;
|
|
19410
19530
|
}
|
|
@@ -19412,13 +19532,13 @@ function memoryOptOut() {
|
|
|
19412
19532
|
function keepMemoryTracked() {
|
|
19413
19533
|
let content = "";
|
|
19414
19534
|
try {
|
|
19415
|
-
content = (0,
|
|
19535
|
+
content = (0, import_node_fs19.readFileSync)(".gitignore", "utf-8");
|
|
19416
19536
|
} catch {
|
|
19417
19537
|
}
|
|
19418
19538
|
if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
|
|
19419
19539
|
try {
|
|
19420
19540
|
const sep5 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
|
|
19421
|
-
(0,
|
|
19541
|
+
(0, import_node_fs19.writeFileSync)(".gitignore", content + sep5 + MEMORY_OPT_OUT_STANZA);
|
|
19422
19542
|
} catch {
|
|
19423
19543
|
return "failed";
|
|
19424
19544
|
}
|
|
@@ -19427,7 +19547,7 @@ function keepMemoryTracked() {
|
|
|
19427
19547
|
function committedVerityState() {
|
|
19428
19548
|
let out2 = "";
|
|
19429
19549
|
try {
|
|
19430
|
-
out2 = (0,
|
|
19550
|
+
out2 = (0, import_node_child_process7.execSync)("git ls-files -z -- .verity", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
19431
19551
|
} catch {
|
|
19432
19552
|
return [];
|
|
19433
19553
|
}
|
|
@@ -19437,12 +19557,12 @@ function untrackVerityState() {
|
|
|
19437
19557
|
const tracked = committedVerityState();
|
|
19438
19558
|
if (tracked.length === 0) return "none";
|
|
19439
19559
|
try {
|
|
19440
|
-
(0,
|
|
19560
|
+
(0, import_node_child_process7.execSync)("git rm -r --cached --quiet -- .verity", { stdio: "pipe" });
|
|
19441
19561
|
const keeps = [".verity/standard.yaml"];
|
|
19442
19562
|
if (memoryPosture() === "committable") keeps.push(".verity/memory");
|
|
19443
19563
|
for (const keep of keeps) {
|
|
19444
19564
|
try {
|
|
19445
|
-
(0,
|
|
19565
|
+
(0, import_node_child_process7.execSync)(`git add -- "${keep}"`, { stdio: "pipe" });
|
|
19446
19566
|
} catch {
|
|
19447
19567
|
}
|
|
19448
19568
|
}
|
|
@@ -19453,26 +19573,26 @@ function untrackVerityState() {
|
|
|
19453
19573
|
}
|
|
19454
19574
|
|
|
19455
19575
|
// src/lib/safe-path.ts
|
|
19456
|
-
var
|
|
19457
|
-
var
|
|
19576
|
+
var import_node_fs20 = require("node:fs");
|
|
19577
|
+
var import_node_path18 = require("node:path");
|
|
19458
19578
|
function resolveInside(baseDir, candidate) {
|
|
19459
19579
|
if (typeof candidate !== "string" || candidate.length === 0) return null;
|
|
19460
|
-
if ((0,
|
|
19461
|
-
const baseAbs = (0,
|
|
19462
|
-
const full = (0,
|
|
19463
|
-
const baseSep = baseAbs.endsWith(
|
|
19580
|
+
if ((0, import_node_path18.isAbsolute)(candidate)) return null;
|
|
19581
|
+
const baseAbs = (0, import_node_path18.resolve)(baseDir);
|
|
19582
|
+
const full = (0, import_node_path18.resolve)(baseAbs, candidate);
|
|
19583
|
+
const baseSep = baseAbs.endsWith(import_node_path18.sep) ? baseAbs : baseAbs + import_node_path18.sep;
|
|
19464
19584
|
if (full !== baseAbs && !full.startsWith(baseSep)) return null;
|
|
19465
19585
|
try {
|
|
19466
|
-
if ((0,
|
|
19467
|
-
const realBase = (0,
|
|
19468
|
-
const realBaseSep = realBase.endsWith(
|
|
19586
|
+
if ((0, import_node_fs20.existsSync)(baseAbs)) {
|
|
19587
|
+
const realBase = (0, import_node_fs20.realpathSync)(baseAbs);
|
|
19588
|
+
const realBaseSep = realBase.endsWith(import_node_path18.sep) ? realBase : realBase + import_node_path18.sep;
|
|
19469
19589
|
let probe = full;
|
|
19470
|
-
while (!(0,
|
|
19471
|
-
const parent = (0,
|
|
19590
|
+
while (!(0, import_node_fs20.existsSync)(probe)) {
|
|
19591
|
+
const parent = (0, import_node_path18.dirname)(probe);
|
|
19472
19592
|
if (parent === probe) break;
|
|
19473
19593
|
probe = parent;
|
|
19474
19594
|
}
|
|
19475
|
-
const realProbe = (0,
|
|
19595
|
+
const realProbe = (0, import_node_fs20.realpathSync)(probe);
|
|
19476
19596
|
if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
|
|
19477
19597
|
}
|
|
19478
19598
|
} catch {
|
|
@@ -19480,37 +19600,37 @@ function resolveInside(baseDir, candidate) {
|
|
|
19480
19600
|
}
|
|
19481
19601
|
return full;
|
|
19482
19602
|
}
|
|
19483
|
-
var O_NOFOLLOW2 = typeof
|
|
19603
|
+
var O_NOFOLLOW2 = typeof import_node_fs20.constants.O_NOFOLLOW === "number" ? import_node_fs20.constants.O_NOFOLLOW : 0;
|
|
19484
19604
|
function readFileInside(baseDir, candidate, maxBytes) {
|
|
19485
19605
|
const full = resolveInside(baseDir, candidate);
|
|
19486
19606
|
if (!full) return null;
|
|
19487
19607
|
let realParent;
|
|
19488
19608
|
let realBase;
|
|
19489
19609
|
try {
|
|
19490
|
-
realParent = (0,
|
|
19491
|
-
realBase = (0,
|
|
19610
|
+
realParent = (0, import_node_fs20.realpathSync)((0, import_node_path18.dirname)(full));
|
|
19611
|
+
realBase = (0, import_node_fs20.realpathSync)((0, import_node_path18.resolve)(baseDir));
|
|
19492
19612
|
} catch {
|
|
19493
19613
|
return null;
|
|
19494
19614
|
}
|
|
19495
|
-
const realBaseSep = realBase.endsWith(
|
|
19615
|
+
const realBaseSep = realBase.endsWith(import_node_path18.sep) ? realBase : realBase + import_node_path18.sep;
|
|
19496
19616
|
if (realParent !== realBase && !realParent.startsWith(realBaseSep)) return null;
|
|
19497
|
-
const target = (0,
|
|
19617
|
+
const target = (0, import_node_path18.join)(realParent, (0, import_node_path18.basename)(full));
|
|
19498
19618
|
let fd = null;
|
|
19499
19619
|
try {
|
|
19500
|
-
fd = (0,
|
|
19501
|
-
const st = (0,
|
|
19620
|
+
fd = (0, import_node_fs20.openSync)(target, import_node_fs20.constants.O_RDONLY | O_NOFOLLOW2);
|
|
19621
|
+
const st = (0, import_node_fs20.fstatSync)(fd);
|
|
19502
19622
|
if (!st.isFile()) return null;
|
|
19503
19623
|
const cap2 = Math.min(maxBytes, st.size);
|
|
19504
19624
|
if (cap2 <= 0) return "";
|
|
19505
19625
|
const buf = Buffer.alloc(cap2);
|
|
19506
|
-
const bytesRead = (0,
|
|
19626
|
+
const bytesRead = (0, import_node_fs20.readSync)(fd, buf, 0, cap2, 0);
|
|
19507
19627
|
return buf.subarray(0, bytesRead).toString("utf-8");
|
|
19508
19628
|
} catch {
|
|
19509
19629
|
return null;
|
|
19510
19630
|
} finally {
|
|
19511
19631
|
if (fd !== null) {
|
|
19512
19632
|
try {
|
|
19513
|
-
(0,
|
|
19633
|
+
(0, import_node_fs20.closeSync)(fd);
|
|
19514
19634
|
} catch {
|
|
19515
19635
|
}
|
|
19516
19636
|
}
|
|
@@ -19593,32 +19713,32 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
|
|
|
19593
19713
|
async function ensureMemoryDir() {
|
|
19594
19714
|
await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
|
|
19595
19715
|
for (const domain of DOMAINS2) {
|
|
19596
|
-
await (0, import_promises9.mkdir)((0,
|
|
19716
|
+
await (0, import_promises9.mkdir)((0, import_node_path19.join)(memoryDir2(), domain), { recursive: true });
|
|
19597
19717
|
}
|
|
19598
|
-
if (!(0,
|
|
19599
|
-
await (0, import_promises9.writeFile)((0,
|
|
19718
|
+
if (!(0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "SCHEMA.md"))) {
|
|
19719
|
+
await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
|
|
19600
19720
|
}
|
|
19601
|
-
if (!(0,
|
|
19602
|
-
await (0, import_promises9.writeFile)((0,
|
|
19721
|
+
if (!(0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "index.md"))) {
|
|
19722
|
+
await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
|
|
19603
19723
|
}
|
|
19604
|
-
if (!(0,
|
|
19605
|
-
await (0, import_promises9.writeFile)((0,
|
|
19724
|
+
if (!(0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "log.md"))) {
|
|
19725
|
+
await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
|
|
19606
19726
|
}
|
|
19607
19727
|
}
|
|
19608
19728
|
async function buildManifest() {
|
|
19609
|
-
if (!(0,
|
|
19729
|
+
if (!(0, import_node_fs21.existsSync)(memoryDir2())) {
|
|
19610
19730
|
return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
|
|
19611
19731
|
}
|
|
19612
19732
|
const nodes = [];
|
|
19613
19733
|
for (const domain of DOMAINS2) {
|
|
19614
|
-
const domainDir = (0,
|
|
19615
|
-
if (!(0,
|
|
19734
|
+
const domainDir = (0, import_node_path19.join)(memoryDir2(), domain);
|
|
19735
|
+
if (!(0, import_node_fs21.existsSync)(domainDir)) continue;
|
|
19616
19736
|
try {
|
|
19617
19737
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
19618
19738
|
for (const file of files) {
|
|
19619
19739
|
if (!file.endsWith(".md")) continue;
|
|
19620
19740
|
const filePath = `${domain}/${file}`;
|
|
19621
|
-
const fullPath = (0,
|
|
19741
|
+
const fullPath = (0, import_node_path19.join)(memoryDir2(), filePath);
|
|
19622
19742
|
try {
|
|
19623
19743
|
const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
19624
19744
|
const hash = (0, import_node_crypto4.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
@@ -19631,13 +19751,13 @@ async function buildManifest() {
|
|
|
19631
19751
|
}
|
|
19632
19752
|
let indexHash = null;
|
|
19633
19753
|
try {
|
|
19634
|
-
const indexContent = await (0, import_promises9.readFile)((0,
|
|
19754
|
+
const indexContent = await (0, import_promises9.readFile)((0, import_node_path19.join)(memoryDir2(), "index.md"), "utf-8");
|
|
19635
19755
|
indexHash = `sha256:${(0, import_node_crypto4.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
|
|
19636
19756
|
} catch {
|
|
19637
19757
|
}
|
|
19638
19758
|
let logLength = 0;
|
|
19639
19759
|
try {
|
|
19640
|
-
const logContent = await (0, import_promises9.readFile)((0,
|
|
19760
|
+
const logContent = await (0, import_promises9.readFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), "utf-8");
|
|
19641
19761
|
logLength = logContent.split("\n").length;
|
|
19642
19762
|
} catch {
|
|
19643
19763
|
}
|
|
@@ -19648,15 +19768,15 @@ function hashContent(content) {
|
|
|
19648
19768
|
}
|
|
19649
19769
|
async function readOnDiskNodes() {
|
|
19650
19770
|
const out2 = /* @__PURE__ */ new Map();
|
|
19651
|
-
if (!(0,
|
|
19771
|
+
if (!(0, import_node_fs21.existsSync)(memoryDir2())) return out2;
|
|
19652
19772
|
for (const domain of DOMAINS2) {
|
|
19653
|
-
const domainDir = (0,
|
|
19654
|
-
if (!(0,
|
|
19773
|
+
const domainDir = (0, import_node_path19.join)(memoryDir2(), domain);
|
|
19774
|
+
if (!(0, import_node_fs21.existsSync)(domainDir)) continue;
|
|
19655
19775
|
try {
|
|
19656
19776
|
for (const file of await (0, import_promises9.readdir)(domainDir)) {
|
|
19657
19777
|
if (!file.endsWith(".md")) continue;
|
|
19658
19778
|
try {
|
|
19659
|
-
out2.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0,
|
|
19779
|
+
out2.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path19.join)(domainDir, file), "utf-8")));
|
|
19660
19780
|
} catch {
|
|
19661
19781
|
}
|
|
19662
19782
|
}
|
|
@@ -19693,7 +19813,7 @@ async function recordSyncedNodePaths() {
|
|
|
19693
19813
|
}
|
|
19694
19814
|
}
|
|
19695
19815
|
async function writeFileAtomic(path, content) {
|
|
19696
|
-
await (0, import_promises9.mkdir)((0,
|
|
19816
|
+
await (0, import_promises9.mkdir)((0, import_node_path19.dirname)(path), { recursive: true });
|
|
19697
19817
|
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
19698
19818
|
await (0, import_promises9.writeFile)(tmp, content);
|
|
19699
19819
|
await (0, import_promises9.rename)(tmp, path);
|
|
@@ -19707,8 +19827,8 @@ async function computeEditedNodeUploads() {
|
|
|
19707
19827
|
const uploads = [];
|
|
19708
19828
|
for (const [path, prevHash] of prev) {
|
|
19709
19829
|
if (prevHash == null) continue;
|
|
19710
|
-
const full = (0,
|
|
19711
|
-
if (!(0,
|
|
19830
|
+
const full = (0, import_node_path19.join)(memoryDir2(), path);
|
|
19831
|
+
if (!(0, import_node_fs21.existsSync)(full)) continue;
|
|
19712
19832
|
let content;
|
|
19713
19833
|
try {
|
|
19714
19834
|
content = await (0, import_promises9.readFile)(full, "utf-8");
|
|
@@ -19752,8 +19872,8 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
19752
19872
|
const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
|
|
19753
19873
|
for (const n of notes) logLines.push(` - ${n}`);
|
|
19754
19874
|
try {
|
|
19755
|
-
const existing = (0,
|
|
19756
|
-
await (0, import_promises9.writeFile)((0,
|
|
19875
|
+
const existing = (0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
|
|
19876
|
+
await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
|
|
19757
19877
|
} catch {
|
|
19758
19878
|
}
|
|
19759
19879
|
if (opts.baseline === "written") await mergeSyncBaseline(synced);
|
|
@@ -19763,7 +19883,7 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
19763
19883
|
async function mergeSyncBaseline(entries) {
|
|
19764
19884
|
if (entries.size === 0) return;
|
|
19765
19885
|
try {
|
|
19766
|
-
if ((0,
|
|
19886
|
+
if ((0, import_node_fs21.existsSync)(syncStateFile())) {
|
|
19767
19887
|
try {
|
|
19768
19888
|
JSON.parse(await (0, import_promises9.readFile)(syncStateFile(), "utf-8"));
|
|
19769
19889
|
} catch {
|
|
@@ -19791,7 +19911,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
19791
19911
|
notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
|
|
19792
19912
|
}
|
|
19793
19913
|
}
|
|
19794
|
-
if ((0,
|
|
19914
|
+
if ((0, import_node_fs21.existsSync)(fullPath)) {
|
|
19795
19915
|
let existing = "";
|
|
19796
19916
|
try {
|
|
19797
19917
|
existing = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
@@ -19807,7 +19927,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
19807
19927
|
notes.push(`${write.path}: updated from server (untouched here since the server delivered it)`);
|
|
19808
19928
|
}
|
|
19809
19929
|
}
|
|
19810
|
-
await (0, import_promises9.mkdir)((0,
|
|
19930
|
+
await (0, import_promises9.mkdir)((0, import_node_path19.dirname)(fullPath), { recursive: true });
|
|
19811
19931
|
await (0, import_promises9.writeFile)(fullPath, content);
|
|
19812
19932
|
return { written: true, syncedHash: hashContent(content), notes };
|
|
19813
19933
|
}
|
|
@@ -19848,8 +19968,8 @@ async function regenerateIndex() {
|
|
|
19848
19968
|
];
|
|
19849
19969
|
let totalNodes = 0;
|
|
19850
19970
|
for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
|
|
19851
|
-
const domainDir = (0,
|
|
19852
|
-
if (!(0,
|
|
19971
|
+
const domainDir = (0, import_node_path19.join)(memoryDir2(), domain);
|
|
19972
|
+
if (!(0, import_node_fs21.existsSync)(domainDir)) continue;
|
|
19853
19973
|
try {
|
|
19854
19974
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
19855
19975
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
@@ -19859,7 +19979,7 @@ async function regenerateIndex() {
|
|
|
19859
19979
|
for (const file of mdFiles.sort()) {
|
|
19860
19980
|
const slug = file.replace(/\.md$/, "");
|
|
19861
19981
|
try {
|
|
19862
|
-
const content = await (0, import_promises9.readFile)((0,
|
|
19982
|
+
const content = await (0, import_promises9.readFile)((0, import_node_path19.join)(domainDir, file), "utf-8");
|
|
19863
19983
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
19864
19984
|
const kind = pickFrontmatter(content, "kind") ?? "-";
|
|
19865
19985
|
const confidence = pickFrontmatter(content, "confidence");
|
|
@@ -19883,7 +20003,7 @@ async function regenerateIndex() {
|
|
|
19883
20003
|
lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
|
|
19884
20004
|
}
|
|
19885
20005
|
const next = lines.join("\n") + "\n";
|
|
19886
|
-
const indexPath = (0,
|
|
20006
|
+
const indexPath = (0, import_node_path19.join)(memoryDir2(), "index.md");
|
|
19887
20007
|
let existing = null;
|
|
19888
20008
|
try {
|
|
19889
20009
|
existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
|
|
@@ -20280,9 +20400,9 @@ function hasLegacyMemoryBlock(text) {
|
|
|
20280
20400
|
return findMarker(text, LEGACY_MD_START) !== -1;
|
|
20281
20401
|
}
|
|
20282
20402
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
20283
|
-
const claudeMdPath = (0,
|
|
20403
|
+
const claudeMdPath = (0, import_node_path19.join)(cwd, "CLAUDE.md");
|
|
20284
20404
|
let existing = "";
|
|
20285
|
-
if ((0,
|
|
20405
|
+
if ((0, import_node_fs21.existsSync)(claudeMdPath)) {
|
|
20286
20406
|
existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
|
|
20287
20407
|
}
|
|
20288
20408
|
let startTag = CLAUDE_MD_START;
|
|
@@ -20423,9 +20543,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
|
|
|
20423
20543
|
`;
|
|
20424
20544
|
|
|
20425
20545
|
// src/lib/dossier-session.ts
|
|
20426
|
-
var
|
|
20546
|
+
var import_node_fs26 = require("node:fs");
|
|
20427
20547
|
var import_node_crypto8 = require("node:crypto");
|
|
20428
|
-
var
|
|
20548
|
+
var import_node_path22 = require("node:path");
|
|
20429
20549
|
|
|
20430
20550
|
// src/lib/pending-repeat.ts
|
|
20431
20551
|
var STOP = /* @__PURE__ */ new Set([
|
|
@@ -20530,8 +20650,8 @@ function statementAnchorKey(file, patternId) {
|
|
|
20530
20650
|
|
|
20531
20651
|
// src/lib/dossier/log.ts
|
|
20532
20652
|
var import_node_crypto5 = require("node:crypto");
|
|
20533
|
-
var
|
|
20534
|
-
var
|
|
20653
|
+
var import_node_fs22 = require("node:fs");
|
|
20654
|
+
var import_node_path20 = require("node:path");
|
|
20535
20655
|
var CRC_TABLE = (() => {
|
|
20536
20656
|
const t = new Int32Array(256);
|
|
20537
20657
|
for (let i2 = 0; i2 < 256; i2++) {
|
|
@@ -20550,13 +20670,13 @@ function crc32(s) {
|
|
|
20550
20670
|
function openDossier(identity) {
|
|
20551
20671
|
try {
|
|
20552
20672
|
const dir = dossierDir(identity);
|
|
20553
|
-
(0,
|
|
20673
|
+
(0, import_node_fs22.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
20554
20674
|
return {
|
|
20555
20675
|
dir,
|
|
20556
20676
|
identity,
|
|
20557
|
-
eventsPath: (0,
|
|
20558
|
-
foldPath: (0,
|
|
20559
|
-
rotatedDir: (0,
|
|
20677
|
+
eventsPath: (0, import_node_path20.join)(dir, "events.jsonl"),
|
|
20678
|
+
foldPath: (0, import_node_path20.join)(dir, "fold.json"),
|
|
20679
|
+
rotatedDir: (0, import_node_path20.join)(dir, "rotated")
|
|
20560
20680
|
};
|
|
20561
20681
|
} catch {
|
|
20562
20682
|
return null;
|
|
@@ -20618,7 +20738,7 @@ function appendEvent(d, ev) {
|
|
|
20618
20738
|
at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
20619
20739
|
...ev
|
|
20620
20740
|
});
|
|
20621
|
-
(0,
|
|
20741
|
+
(0, import_node_fs22.appendFileSync)(d.eventsPath, line2, { mode: 384 });
|
|
20622
20742
|
return true;
|
|
20623
20743
|
} catch {
|
|
20624
20744
|
return false;
|
|
@@ -20626,14 +20746,14 @@ function appendEvent(d, ev) {
|
|
|
20626
20746
|
}
|
|
20627
20747
|
function rotateIfNeeded2(d) {
|
|
20628
20748
|
try {
|
|
20629
|
-
if (!(0,
|
|
20630
|
-
if ((0,
|
|
20631
|
-
(0,
|
|
20632
|
-
(0,
|
|
20633
|
-
const kept = (0,
|
|
20749
|
+
if (!(0, import_node_fs22.existsSync)(d.eventsPath)) return;
|
|
20750
|
+
if ((0, import_node_fs22.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
|
|
20751
|
+
(0, import_node_fs22.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
|
|
20752
|
+
(0, import_node_fs22.renameSync)(d.eventsPath, (0, import_node_path20.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
|
|
20753
|
+
const kept = (0, import_node_fs22.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
20634
20754
|
for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
|
|
20635
20755
|
try {
|
|
20636
|
-
(0,
|
|
20756
|
+
(0, import_node_fs22.renameSync)((0, import_node_path20.join)(d.rotatedDir, stale), (0, import_node_path20.join)(d.rotatedDir, `${stale}.pruned`));
|
|
20637
20757
|
} catch {
|
|
20638
20758
|
}
|
|
20639
20759
|
}
|
|
@@ -20643,8 +20763,8 @@ function rotateIfNeeded2(d) {
|
|
|
20643
20763
|
|
|
20644
20764
|
// src/lib/dossier/fold-dossier.ts
|
|
20645
20765
|
var import_node_crypto6 = require("node:crypto");
|
|
20646
|
-
var
|
|
20647
|
-
var
|
|
20766
|
+
var import_node_fs23 = require("node:fs");
|
|
20767
|
+
var import_node_path21 = require("node:path");
|
|
20648
20768
|
var EMPTY_CAPABILITIES = () => ({
|
|
20649
20769
|
human_reachable: { value: "unknown", tier: "unknown" },
|
|
20650
20770
|
authorship_observability: { value: "unknown", tier: "unknown" },
|
|
@@ -20695,12 +20815,12 @@ function foldDossier(d, opts = {}) {
|
|
|
20695
20815
|
}
|
|
20696
20816
|
};
|
|
20697
20817
|
try {
|
|
20698
|
-
if ((0,
|
|
20699
|
-
const files = (0,
|
|
20818
|
+
if ((0, import_node_fs23.existsSync)(d.rotatedDir)) {
|
|
20819
|
+
const files = (0, import_node_fs23.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
20700
20820
|
state.meta.rotations = files.length;
|
|
20701
20821
|
for (const f of files) {
|
|
20702
20822
|
try {
|
|
20703
|
-
ingest((0,
|
|
20823
|
+
ingest((0, import_node_fs23.readFileSync)((0, import_node_path21.join)(d.rotatedDir, f), "utf8"));
|
|
20704
20824
|
} catch {
|
|
20705
20825
|
state.meta.dropped_lines++;
|
|
20706
20826
|
}
|
|
@@ -20709,9 +20829,9 @@ function foldDossier(d, opts = {}) {
|
|
|
20709
20829
|
} catch {
|
|
20710
20830
|
}
|
|
20711
20831
|
try {
|
|
20712
|
-
if ((0,
|
|
20713
|
-
state.meta.upto_offset = (0,
|
|
20714
|
-
ingest((0,
|
|
20832
|
+
if ((0, import_node_fs23.existsSync)(d.eventsPath)) {
|
|
20833
|
+
state.meta.upto_offset = (0, import_node_fs23.statSync)(d.eventsPath).size;
|
|
20834
|
+
ingest((0, import_node_fs23.readFileSync)(d.eventsPath, "utf8"));
|
|
20715
20835
|
}
|
|
20716
20836
|
} catch {
|
|
20717
20837
|
}
|
|
@@ -20982,7 +21102,7 @@ function applyBounds(state, input) {
|
|
|
20982
21102
|
}
|
|
20983
21103
|
|
|
20984
21104
|
// src/lib/dossier/cache.ts
|
|
20985
|
-
var
|
|
21105
|
+
var import_node_fs24 = require("node:fs");
|
|
20986
21106
|
function compactState(s) {
|
|
20987
21107
|
const ms = (iso) => Date.parse(iso) || 0;
|
|
20988
21108
|
return {
|
|
@@ -21111,20 +21231,20 @@ function encodeState(s) {
|
|
|
21111
21231
|
function writeFoldCache(d, state) {
|
|
21112
21232
|
try {
|
|
21113
21233
|
const tmp = `${d.foldPath}.${process.pid}.tmp`;
|
|
21114
|
-
(0,
|
|
21115
|
-
(0,
|
|
21234
|
+
(0, import_node_fs24.writeFileSync)(tmp, encodeState(state), { mode: 384 });
|
|
21235
|
+
(0, import_node_fs24.renameSync)(tmp, d.foldPath);
|
|
21116
21236
|
} catch {
|
|
21117
21237
|
}
|
|
21118
21238
|
}
|
|
21119
21239
|
function readFoldCache(d) {
|
|
21120
21240
|
try {
|
|
21121
|
-
if (!(0,
|
|
21122
|
-
const raw = JSON.parse((0,
|
|
21241
|
+
if (!(0, import_node_fs24.existsSync)(d.foldPath)) return null;
|
|
21242
|
+
const raw = JSON.parse((0, import_node_fs24.readFileSync)(d.foldPath, "utf8"));
|
|
21123
21243
|
if (raw?.v !== 1) return null;
|
|
21124
21244
|
const cached2 = expandState(raw);
|
|
21125
21245
|
if (!cached2?.meta) return null;
|
|
21126
|
-
const size = (0,
|
|
21127
|
-
const rotations = (0,
|
|
21246
|
+
const size = (0, import_node_fs24.existsSync)(d.eventsPath) ? (0, import_node_fs24.statSync)(d.eventsPath).size : 0;
|
|
21247
|
+
const rotations = (0, import_node_fs24.existsSync)(d.rotatedDir) ? (0, import_node_fs24.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
|
|
21128
21248
|
if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
|
|
21129
21249
|
return cached2;
|
|
21130
21250
|
} catch {
|
|
@@ -21175,13 +21295,13 @@ function assessContinuity(i2) {
|
|
|
21175
21295
|
|
|
21176
21296
|
// src/lib/dossier/reanchor.ts
|
|
21177
21297
|
var import_node_crypto7 = require("node:crypto");
|
|
21178
|
-
var
|
|
21298
|
+
var import_node_fs25 = require("node:fs");
|
|
21179
21299
|
function lineSha(text) {
|
|
21180
21300
|
return (0, import_node_crypto7.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
|
|
21181
21301
|
}
|
|
21182
21302
|
function fileHash(path) {
|
|
21183
21303
|
try {
|
|
21184
|
-
return (0, import_node_crypto7.createHash)("sha256").update((0,
|
|
21304
|
+
return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
|
|
21185
21305
|
} catch {
|
|
21186
21306
|
return null;
|
|
21187
21307
|
}
|
|
@@ -21553,20 +21673,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
|
|
|
21553
21673
|
let sessions = 0;
|
|
21554
21674
|
try {
|
|
21555
21675
|
const dir = treeDir(identity);
|
|
21556
|
-
if (!(0,
|
|
21557
|
-
for (const entry of (0,
|
|
21676
|
+
if (!(0, import_node_fs26.existsSync)(dir)) return { paths: [], sessions: 0 };
|
|
21677
|
+
for (const entry of (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true })) {
|
|
21558
21678
|
if (!entry.isDirectory()) continue;
|
|
21559
21679
|
if (entry.name === identity.sessionKey) continue;
|
|
21560
|
-
const log = (0,
|
|
21680
|
+
const log = (0, import_node_path22.join)(dir, entry.name, "events.jsonl");
|
|
21561
21681
|
try {
|
|
21562
|
-
if (!(0,
|
|
21563
|
-
if (now - (0,
|
|
21682
|
+
if (!(0, import_node_fs26.existsSync)(log)) continue;
|
|
21683
|
+
if (now - (0, import_node_fs26.statSync)(log).mtimeMs > windowMs) continue;
|
|
21564
21684
|
const sib = {
|
|
21565
|
-
dir: (0,
|
|
21685
|
+
dir: (0, import_node_path22.join)(dir, entry.name),
|
|
21566
21686
|
identity,
|
|
21567
21687
|
eventsPath: log,
|
|
21568
|
-
foldPath: (0,
|
|
21569
|
-
rotatedDir: (0,
|
|
21688
|
+
foldPath: (0, import_node_path22.join)(dir, entry.name, "fold.json"),
|
|
21689
|
+
rotatedDir: (0, import_node_path22.join)(dir, entry.name, "rotated")
|
|
21570
21690
|
};
|
|
21571
21691
|
const state = readFoldCache(sib) ?? foldDossier(sib);
|
|
21572
21692
|
sessions++;
|
|
@@ -21594,25 +21714,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
21594
21714
|
let removed = 0;
|
|
21595
21715
|
try {
|
|
21596
21716
|
const mine = dossierDir(identity);
|
|
21597
|
-
const userDir = (0,
|
|
21598
|
-
if (!(0,
|
|
21717
|
+
const userDir = (0, import_node_path22.dirname)((0, import_node_path22.dirname)(mine));
|
|
21718
|
+
if (!(0, import_node_fs26.existsSync)(userDir)) return 0;
|
|
21599
21719
|
const cutoff = Date.now() - maxAgeMs;
|
|
21600
|
-
for (const tree of (0,
|
|
21720
|
+
for (const tree of (0, import_node_fs26.readdirSync)(userDir, { withFileTypes: true })) {
|
|
21601
21721
|
if (!tree.isDirectory()) continue;
|
|
21602
|
-
const treePath = (0,
|
|
21722
|
+
const treePath = (0, import_node_path22.join)(userDir, tree.name);
|
|
21603
21723
|
let live = 0;
|
|
21604
|
-
for (const entry of (0,
|
|
21724
|
+
for (const entry of (0, import_node_fs26.readdirSync)(treePath, { withFileTypes: true })) {
|
|
21605
21725
|
if (!entry.isDirectory()) continue;
|
|
21606
|
-
const dir = (0,
|
|
21726
|
+
const dir = (0, import_node_path22.join)(treePath, entry.name);
|
|
21607
21727
|
if (dir === mine) {
|
|
21608
21728
|
live++;
|
|
21609
21729
|
continue;
|
|
21610
21730
|
}
|
|
21611
21731
|
try {
|
|
21612
|
-
const log = (0,
|
|
21613
|
-
const at = (0,
|
|
21732
|
+
const log = (0, import_node_path22.join)(dir, "events.jsonl");
|
|
21733
|
+
const at = (0, import_node_fs26.existsSync)(log) ? (0, import_node_fs26.statSync)(log).mtimeMs : (0, import_node_fs26.statSync)(dir).mtimeMs;
|
|
21614
21734
|
if (at < cutoff) {
|
|
21615
|
-
(0,
|
|
21735
|
+
(0, import_node_fs26.rmSync)(dir, { recursive: true, force: true });
|
|
21616
21736
|
removed++;
|
|
21617
21737
|
} else {
|
|
21618
21738
|
live++;
|
|
@@ -21622,7 +21742,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
21622
21742
|
}
|
|
21623
21743
|
if (live === 0) {
|
|
21624
21744
|
try {
|
|
21625
|
-
(0,
|
|
21745
|
+
(0, import_node_fs26.rmSync)(treePath, { recursive: false, force: false });
|
|
21626
21746
|
} catch {
|
|
21627
21747
|
}
|
|
21628
21748
|
}
|
|
@@ -21639,8 +21759,8 @@ function sessionDossier(token, sessionId) {
|
|
|
21639
21759
|
}
|
|
21640
21760
|
function hasActiveGoal(d) {
|
|
21641
21761
|
try {
|
|
21642
|
-
if (!(0,
|
|
21643
|
-
return (0,
|
|
21762
|
+
if (!(0, import_node_fs26.existsSync)(d.eventsPath)) return false;
|
|
21763
|
+
return (0, import_node_fs26.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
|
|
21644
21764
|
} catch {
|
|
21645
21765
|
return false;
|
|
21646
21766
|
}
|
|
@@ -21664,7 +21784,7 @@ function recordTurn(d, t) {
|
|
|
21664
21784
|
for (const a of t.authored) {
|
|
21665
21785
|
const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
|
|
21666
21786
|
const prior = t.known?.authored?.get(a.p);
|
|
21667
|
-
const hash = fileHash((0,
|
|
21787
|
+
const hash = fileHash((0, import_node_path22.join)(root, a.p));
|
|
21668
21788
|
const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
|
|
21669
21789
|
const adds = Math.max(0, a.a - (prior?.adds ?? 0));
|
|
21670
21790
|
const dels = Math.max(0, a.d - (prior?.dels ?? 0));
|
|
@@ -21697,7 +21817,7 @@ function recordTurn(d, t) {
|
|
|
21697
21817
|
}
|
|
21698
21818
|
const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
|
|
21699
21819
|
for (const u of t.unobserved) {
|
|
21700
|
-
const hash = fileHash((0,
|
|
21820
|
+
const hash = fileHash((0, import_node_path22.join)(root, u.p));
|
|
21701
21821
|
if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
|
|
21702
21822
|
appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
|
|
21703
21823
|
}
|
|
@@ -21732,8 +21852,8 @@ function recordVerdict(d, v) {
|
|
|
21732
21852
|
if (!sent.has(f.file)) continue;
|
|
21733
21853
|
if (!lines.has(f.file)) {
|
|
21734
21854
|
try {
|
|
21735
|
-
const abs = (0,
|
|
21736
|
-
lines.set(f.file, (0,
|
|
21855
|
+
const abs = (0, import_node_path22.join)(root, f.file);
|
|
21856
|
+
lines.set(f.file, (0, import_node_fs26.existsSync)(abs) ? (0, import_node_fs26.readFileSync)(abs, "utf8").split("\n") : null);
|
|
21737
21857
|
} catch {
|
|
21738
21858
|
lines.set(f.file, null);
|
|
21739
21859
|
}
|
|
@@ -21833,8 +21953,8 @@ function recallMemory(d, identity, opts) {
|
|
|
21833
21953
|
budgetBytes: opts.budgetBytes,
|
|
21834
21954
|
readFileLines: (file) => {
|
|
21835
21955
|
try {
|
|
21836
|
-
const abs = (0,
|
|
21837
|
-
return (0,
|
|
21956
|
+
const abs = (0, import_node_path22.join)(root, file);
|
|
21957
|
+
return (0, import_node_fs26.existsSync)(abs) ? (0, import_node_fs26.readFileSync)(abs, "utf8").split("\n") : null;
|
|
21838
21958
|
} catch {
|
|
21839
21959
|
return null;
|
|
21840
21960
|
}
|
|
@@ -22002,21 +22122,21 @@ async function fireClassify(prompt, sessionId, globals) {
|
|
|
22002
22122
|
}
|
|
22003
22123
|
|
|
22004
22124
|
// src/commands/lifecycle.ts
|
|
22005
|
-
var
|
|
22006
|
-
var
|
|
22125
|
+
var import_node_fs29 = require("node:fs");
|
|
22126
|
+
var import_node_path26 = require("node:path");
|
|
22007
22127
|
|
|
22008
22128
|
// src/lib/baseline.ts
|
|
22009
|
-
var
|
|
22010
|
-
var
|
|
22129
|
+
var import_node_fs28 = require("node:fs");
|
|
22130
|
+
var import_node_path25 = require("node:path");
|
|
22011
22131
|
var import_node_crypto10 = require("node:crypto");
|
|
22012
22132
|
|
|
22013
22133
|
// src/lib/snapshot.ts
|
|
22014
|
-
var
|
|
22015
|
-
var
|
|
22016
|
-
var
|
|
22134
|
+
var import_node_fs27 = require("node:fs");
|
|
22135
|
+
var import_node_path24 = require("node:path");
|
|
22136
|
+
var import_node_child_process8 = require("node:child_process");
|
|
22017
22137
|
|
|
22018
22138
|
// src/lib/files.ts
|
|
22019
|
-
var
|
|
22139
|
+
var import_node_path23 = require("node:path");
|
|
22020
22140
|
var LANG_MAP = {
|
|
22021
22141
|
// Analyzable (static analysis + Gemini)
|
|
22022
22142
|
ts: "typescript",
|
|
@@ -22084,7 +22204,7 @@ var LANG_MAP = {
|
|
|
22084
22204
|
mk: "make"
|
|
22085
22205
|
};
|
|
22086
22206
|
function detectLanguage(filepath) {
|
|
22087
|
-
const ext = (0,
|
|
22207
|
+
const ext = (0, import_node_path23.extname)(filepath).slice(1);
|
|
22088
22208
|
return LANG_MAP[ext] ?? ext;
|
|
22089
22209
|
}
|
|
22090
22210
|
function sortByMtime(files) {
|
|
@@ -22175,16 +22295,16 @@ function collectCodeDelta(files, opts) {
|
|
|
22175
22295
|
|
|
22176
22296
|
// src/lib/snapshot.ts
|
|
22177
22297
|
function generateSnapshotDiffs(files) {
|
|
22178
|
-
if (!(0,
|
|
22298
|
+
if (!(0, import_node_fs27.existsSync)(SNAPSHOT_DIR)) {
|
|
22179
22299
|
return { diffs: [], has_snapshots: false };
|
|
22180
22300
|
}
|
|
22181
22301
|
const diffs = [];
|
|
22182
22302
|
for (const file of files) {
|
|
22183
22303
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
22184
|
-
const snapshotPath = (0,
|
|
22304
|
+
const snapshotPath = (0, import_node_path24.join)(SNAPSHOT_DIR, file.path);
|
|
22185
22305
|
const language = file.language ?? detectLanguage(file.path);
|
|
22186
|
-
if ((0,
|
|
22187
|
-
const oldContent = (0,
|
|
22306
|
+
if ((0, import_node_fs27.existsSync)(snapshotPath)) {
|
|
22307
|
+
const oldContent = (0, import_node_fs27.readFileSync)(snapshotPath, "utf-8");
|
|
22188
22308
|
if (oldContent === file.content) continue;
|
|
22189
22309
|
const diff = computeDiff(oldContent, file.content, file.path);
|
|
22190
22310
|
if (diff) {
|
|
@@ -22209,21 +22329,21 @@ function saveSnapshots(files) {
|
|
|
22209
22329
|
const snapshotPaths = /* @__PURE__ */ new Set();
|
|
22210
22330
|
for (const file of files) {
|
|
22211
22331
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
22212
|
-
const snapshotPath = (0,
|
|
22332
|
+
const snapshotPath = (0, import_node_path24.join)(SNAPSHOT_DIR, file.path);
|
|
22213
22333
|
snapshotPaths.add(snapshotPath);
|
|
22214
|
-
(0,
|
|
22215
|
-
(0,
|
|
22334
|
+
(0, import_node_fs27.mkdirSync)((0, import_node_path24.dirname)(snapshotPath), { recursive: true });
|
|
22335
|
+
(0, import_node_fs27.writeFileSync)(snapshotPath, file.content);
|
|
22216
22336
|
}
|
|
22217
22337
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
22218
22338
|
}
|
|
22219
22339
|
function computeDiff(oldContent, newContent, filePath) {
|
|
22220
|
-
const tmpOld = (0,
|
|
22221
|
-
const tmpNew = (0,
|
|
22340
|
+
const tmpOld = (0, import_node_path24.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
22341
|
+
const tmpNew = (0, import_node_path24.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
22222
22342
|
try {
|
|
22223
|
-
(0,
|
|
22224
|
-
(0,
|
|
22225
|
-
(0,
|
|
22226
|
-
const result = (0,
|
|
22343
|
+
(0, import_node_fs27.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
22344
|
+
(0, import_node_fs27.writeFileSync)(tmpOld, oldContent);
|
|
22345
|
+
(0, import_node_fs27.writeFileSync)(tmpNew, newContent);
|
|
22346
|
+
const result = (0, import_node_child_process8.execSync)(
|
|
22227
22347
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
22228
22348
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
22229
22349
|
);
|
|
@@ -22236,32 +22356,32 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
22236
22356
|
return null;
|
|
22237
22357
|
} finally {
|
|
22238
22358
|
try {
|
|
22239
|
-
(0,
|
|
22359
|
+
(0, import_node_fs27.unlinkSync)(tmpOld);
|
|
22240
22360
|
} catch {
|
|
22241
22361
|
}
|
|
22242
22362
|
try {
|
|
22243
|
-
(0,
|
|
22363
|
+
(0, import_node_fs27.unlinkSync)(tmpNew);
|
|
22244
22364
|
} catch {
|
|
22245
22365
|
}
|
|
22246
22366
|
}
|
|
22247
22367
|
}
|
|
22248
22368
|
function cleanStaleSnapshots(dir, keepSet) {
|
|
22249
|
-
if (!(0,
|
|
22369
|
+
if (!(0, import_node_fs27.existsSync)(dir)) return;
|
|
22250
22370
|
try {
|
|
22251
|
-
const entries = (0,
|
|
22371
|
+
const entries = (0, import_node_fs27.readdirSync)(dir, { withFileTypes: true });
|
|
22252
22372
|
for (const entry of entries) {
|
|
22253
22373
|
if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
|
|
22254
|
-
const fullPath = (0,
|
|
22374
|
+
const fullPath = (0, import_node_path24.join)(dir, entry.name);
|
|
22255
22375
|
if (entry.isDirectory()) {
|
|
22256
22376
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
22257
22377
|
try {
|
|
22258
|
-
const remaining = (0,
|
|
22259
|
-
if (remaining.length === 0) (0,
|
|
22378
|
+
const remaining = (0, import_node_fs27.readdirSync)(fullPath);
|
|
22379
|
+
if (remaining.length === 0) (0, import_node_fs27.rmdirSync)(fullPath);
|
|
22260
22380
|
} catch {
|
|
22261
22381
|
}
|
|
22262
22382
|
} else if (!keepSet.has(fullPath)) {
|
|
22263
22383
|
try {
|
|
22264
|
-
(0,
|
|
22384
|
+
(0, import_node_fs27.unlinkSync)(fullPath);
|
|
22265
22385
|
} catch {
|
|
22266
22386
|
}
|
|
22267
22387
|
}
|
|
@@ -22280,20 +22400,20 @@ function sessionKey(sessionId) {
|
|
|
22280
22400
|
return (0, import_node_crypto10.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
22281
22401
|
}
|
|
22282
22402
|
function sessionDir(key) {
|
|
22283
|
-
return (0,
|
|
22403
|
+
return (0, import_node_path25.join)(projectPath(BASELINE_DIR), key);
|
|
22284
22404
|
}
|
|
22285
22405
|
function manifestPath(dir) {
|
|
22286
|
-
return (0,
|
|
22406
|
+
return (0, import_node_path25.join)(dir, "manifest.json");
|
|
22287
22407
|
}
|
|
22288
22408
|
function mirrorPath(dir, repoRelPath) {
|
|
22289
|
-
return (0,
|
|
22409
|
+
return (0, import_node_path25.join)(dir, "files", repoRelPath);
|
|
22290
22410
|
}
|
|
22291
22411
|
var CARRY_FILE = `${BASELINE_DIR}/.carry`;
|
|
22292
22412
|
var CARRY_WINDOW_MS = 12e4;
|
|
22293
22413
|
function writeCarry(sessionId, headSha) {
|
|
22294
22414
|
try {
|
|
22295
|
-
(0,
|
|
22296
|
-
(0,
|
|
22415
|
+
(0, import_node_fs28.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
|
|
22416
|
+
(0, import_node_fs28.writeFileSync)(
|
|
22297
22417
|
projectPath(CARRY_FILE),
|
|
22298
22418
|
JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
|
|
22299
22419
|
);
|
|
@@ -22303,10 +22423,10 @@ function writeCarry(sessionId, headSha) {
|
|
|
22303
22423
|
function claimCarry(newKey) {
|
|
22304
22424
|
const carryPath = projectPath(CARRY_FILE);
|
|
22305
22425
|
try {
|
|
22306
|
-
if (!(0,
|
|
22307
|
-
const carry = JSON.parse((0,
|
|
22426
|
+
if (!(0, import_node_fs28.existsSync)(carryPath)) return null;
|
|
22427
|
+
const carry = JSON.parse((0, import_node_fs28.readFileSync)(carryPath, "utf-8"));
|
|
22308
22428
|
try {
|
|
22309
|
-
(0,
|
|
22429
|
+
(0, import_node_fs28.rmSync)(carryPath, { force: true });
|
|
22310
22430
|
} catch {
|
|
22311
22431
|
}
|
|
22312
22432
|
if (!carry?.from_key || typeof carry.ts !== "number") return null;
|
|
@@ -22317,11 +22437,11 @@ function claimCarry(newKey) {
|
|
|
22317
22437
|
if (!prior) return null;
|
|
22318
22438
|
const toDir = sessionDir(newKey);
|
|
22319
22439
|
try {
|
|
22320
|
-
(0,
|
|
22440
|
+
(0, import_node_fs28.rmSync)(toDir, { recursive: true, force: true });
|
|
22321
22441
|
} catch {
|
|
22322
22442
|
}
|
|
22323
|
-
(0,
|
|
22324
|
-
(0,
|
|
22443
|
+
(0, import_node_fs28.renameSync)(fromDir, toDir);
|
|
22444
|
+
(0, import_node_fs28.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
|
|
22325
22445
|
return readManifest(toDir);
|
|
22326
22446
|
} catch {
|
|
22327
22447
|
return null;
|
|
@@ -22345,21 +22465,21 @@ function captureBaseline(opts = {}) {
|
|
|
22345
22465
|
const head_sha = getCurrentCommit();
|
|
22346
22466
|
const dirty = getDirtyFiles();
|
|
22347
22467
|
try {
|
|
22348
|
-
(0,
|
|
22468
|
+
(0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
|
|
22349
22469
|
} catch {
|
|
22350
22470
|
}
|
|
22351
|
-
const filesDir = (0,
|
|
22471
|
+
const filesDir = (0, import_node_path25.join)(dir, "files");
|
|
22352
22472
|
const mirrored = [];
|
|
22353
22473
|
try {
|
|
22354
|
-
(0,
|
|
22474
|
+
(0, import_node_fs28.mkdirSync)(filesDir, { recursive: true });
|
|
22355
22475
|
for (const p of dirty) {
|
|
22356
22476
|
if (p.includes("..")) continue;
|
|
22357
22477
|
const content = safeReadForMirror(projectPath(p));
|
|
22358
22478
|
if (content === null) continue;
|
|
22359
22479
|
const dest = mirrorPath(dir, p);
|
|
22360
22480
|
try {
|
|
22361
|
-
(0,
|
|
22362
|
-
(0,
|
|
22481
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path25.dirname)(dest), { recursive: true });
|
|
22482
|
+
(0, import_node_fs28.writeFileSync)(dest, content);
|
|
22363
22483
|
mirrored.push(p);
|
|
22364
22484
|
} catch {
|
|
22365
22485
|
}
|
|
@@ -22374,8 +22494,8 @@ function captureBaseline(opts = {}) {
|
|
|
22374
22494
|
version: BASELINE_VERSION
|
|
22375
22495
|
};
|
|
22376
22496
|
try {
|
|
22377
|
-
(0,
|
|
22378
|
-
(0,
|
|
22497
|
+
(0, import_node_fs28.mkdirSync)(dir, { recursive: true });
|
|
22498
|
+
(0, import_node_fs28.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
|
|
22379
22499
|
} catch {
|
|
22380
22500
|
}
|
|
22381
22501
|
pruneOldBaselines();
|
|
@@ -22386,9 +22506,9 @@ function readBaseline(sessionId) {
|
|
|
22386
22506
|
}
|
|
22387
22507
|
function readManifest(dir) {
|
|
22388
22508
|
const mp = manifestPath(dir);
|
|
22389
|
-
if (!(0,
|
|
22509
|
+
if (!(0, import_node_fs28.existsSync)(mp)) return null;
|
|
22390
22510
|
try {
|
|
22391
|
-
const parsed = JSON.parse((0,
|
|
22511
|
+
const parsed = JSON.parse((0, import_node_fs28.readFileSync)(mp, "utf-8"));
|
|
22392
22512
|
if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
|
|
22393
22513
|
return null;
|
|
22394
22514
|
}
|
|
@@ -22419,9 +22539,9 @@ function preImage(repoRelPath, baseline) {
|
|
|
22419
22539
|
function resolvePreImage(repoRelPath, baseline) {
|
|
22420
22540
|
if (baseline.dirty_paths.includes(repoRelPath)) {
|
|
22421
22541
|
const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
|
|
22422
|
-
if ((0,
|
|
22542
|
+
if ((0, import_node_fs28.existsSync)(mp)) {
|
|
22423
22543
|
try {
|
|
22424
|
-
return { content: (0,
|
|
22544
|
+
return { content: (0, import_node_fs28.readFileSync)(mp, "utf-8"), existed: true };
|
|
22425
22545
|
} catch {
|
|
22426
22546
|
}
|
|
22427
22547
|
}
|
|
@@ -22466,8 +22586,8 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
22466
22586
|
const content = safeReadForMirror(projectPath(p));
|
|
22467
22587
|
if (content === null) continue;
|
|
22468
22588
|
const dest = mirrorPath(dir, p);
|
|
22469
|
-
(0,
|
|
22470
|
-
(0,
|
|
22589
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path25.dirname)(dest), { recursive: true });
|
|
22590
|
+
(0, import_node_fs28.writeFileSync)(dest, content);
|
|
22471
22591
|
dirty.add(p);
|
|
22472
22592
|
adopted++;
|
|
22473
22593
|
} catch {
|
|
@@ -22476,7 +22596,7 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
22476
22596
|
if (adopted === 0) return 0;
|
|
22477
22597
|
try {
|
|
22478
22598
|
const updated = { ...baseline, dirty_paths: [...dirty] };
|
|
22479
|
-
(0,
|
|
22599
|
+
(0, import_node_fs28.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
|
|
22480
22600
|
preImageCache.delete(baseline);
|
|
22481
22601
|
} catch {
|
|
22482
22602
|
return 0;
|
|
@@ -22487,7 +22607,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
22487
22607
|
const pre = preImage(repoRelPath, baseline);
|
|
22488
22608
|
let current;
|
|
22489
22609
|
try {
|
|
22490
|
-
current = (0,
|
|
22610
|
+
current = (0, import_node_fs28.readFileSync)(projectPath(repoRelPath), "utf-8");
|
|
22491
22611
|
} catch {
|
|
22492
22612
|
return pre.existed;
|
|
22493
22613
|
}
|
|
@@ -22496,8 +22616,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
22496
22616
|
}
|
|
22497
22617
|
function safeReadForMirror(absPath) {
|
|
22498
22618
|
try {
|
|
22499
|
-
if ((0,
|
|
22500
|
-
const buf = (0,
|
|
22619
|
+
if ((0, import_node_fs28.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
|
|
22620
|
+
const buf = (0, import_node_fs28.readFileSync)(absPath);
|
|
22501
22621
|
if (buf.includes(0)) return null;
|
|
22502
22622
|
return buf.toString("utf-8");
|
|
22503
22623
|
} catch {
|
|
@@ -22508,18 +22628,18 @@ function pruneOldBaselines() {
|
|
|
22508
22628
|
const root = projectPath(BASELINE_DIR);
|
|
22509
22629
|
let entries;
|
|
22510
22630
|
try {
|
|
22511
|
-
entries = (0,
|
|
22631
|
+
entries = (0, import_node_fs28.readdirSync)(root);
|
|
22512
22632
|
} catch {
|
|
22513
22633
|
return;
|
|
22514
22634
|
}
|
|
22515
22635
|
const now = Date.now();
|
|
22516
22636
|
for (const name2 of entries) {
|
|
22517
|
-
const dir = (0,
|
|
22637
|
+
const dir = (0, import_node_path25.join)(root, name2);
|
|
22518
22638
|
const manifest = readManifest(dir);
|
|
22519
22639
|
if (!manifest) {
|
|
22520
22640
|
try {
|
|
22521
|
-
if (now - (0,
|
|
22522
|
-
(0,
|
|
22641
|
+
if (now - (0, import_node_fs28.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
|
|
22642
|
+
(0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
|
|
22523
22643
|
}
|
|
22524
22644
|
} catch {
|
|
22525
22645
|
}
|
|
@@ -22527,7 +22647,7 @@ function pruneOldBaselines() {
|
|
|
22527
22647
|
}
|
|
22528
22648
|
if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
|
|
22529
22649
|
try {
|
|
22530
|
-
(0,
|
|
22650
|
+
(0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
|
|
22531
22651
|
} catch {
|
|
22532
22652
|
}
|
|
22533
22653
|
}
|
|
@@ -22702,8 +22822,8 @@ function buildCompactionContext(session) {
|
|
|
22702
22822
|
commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
|
|
22703
22823
|
readFileLines: (file) => {
|
|
22704
22824
|
try {
|
|
22705
|
-
const abs = (0,
|
|
22706
|
-
return (0,
|
|
22825
|
+
const abs = (0, import_node_path26.join)(root, file);
|
|
22826
|
+
return (0, import_node_fs29.existsSync)(abs) ? (0, import_node_fs29.readFileSync)(abs, "utf8").split("\n") : null;
|
|
22707
22827
|
} catch {
|
|
22708
22828
|
return null;
|
|
22709
22829
|
}
|
|
@@ -22760,24 +22880,24 @@ async function readHookStdin() {
|
|
|
22760
22880
|
|
|
22761
22881
|
// src/commands/standard.ts
|
|
22762
22882
|
var import_promises13 = require("node:fs/promises");
|
|
22763
|
-
var
|
|
22883
|
+
var import_node_fs36 = require("node:fs");
|
|
22764
22884
|
var import_yaml3 = __toESM2(require_dist());
|
|
22765
22885
|
|
|
22766
22886
|
// src/lib/synthesize.ts
|
|
22767
|
-
var
|
|
22768
|
-
var
|
|
22887
|
+
var import_node_child_process10 = require("node:child_process");
|
|
22888
|
+
var import_node_fs32 = require("node:fs");
|
|
22769
22889
|
var import_promises10 = require("node:fs/promises");
|
|
22770
|
-
var
|
|
22890
|
+
var import_node_path29 = require("node:path");
|
|
22771
22891
|
var import_yaml = __toESM2(require_dist());
|
|
22772
22892
|
|
|
22773
22893
|
// src/lib/data-dir.ts
|
|
22774
|
-
var
|
|
22775
|
-
var
|
|
22894
|
+
var import_node_fs30 = require("node:fs");
|
|
22895
|
+
var import_node_path27 = require("node:path");
|
|
22776
22896
|
function resolveDataDir() {
|
|
22777
22897
|
const candidates2 = [
|
|
22778
|
-
(0,
|
|
22898
|
+
(0, import_node_path27.join)(__dirname, "..", "data"),
|
|
22779
22899
|
// installed: node_modules/@codacy/verity-cli/data
|
|
22780
|
-
(0,
|
|
22900
|
+
(0, import_node_path27.join)(__dirname, "..", "..", "data"),
|
|
22781
22901
|
// edge case: nested resolution
|
|
22782
22902
|
// THE COMMITTED SOURCE, for a source checkout that has not been built.
|
|
22783
22903
|
// cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
|
|
@@ -22786,14 +22906,14 @@ function resolveDataDir() {
|
|
|
22786
22906
|
// without this the synthesizer throws "Could not find Verity skill data"
|
|
22787
22907
|
// for every test and every `verity` run from source. Resolved from this
|
|
22788
22908
|
// module's own location, never the cwd: see the warning below.
|
|
22789
|
-
(0,
|
|
22909
|
+
(0, import_node_path27.join)(__dirname, "..", "..", "client"),
|
|
22790
22910
|
// bundled: cli/bin/ → ../../client
|
|
22791
|
-
(0,
|
|
22911
|
+
(0, import_node_path27.join)(__dirname, "..", "..", "..", "client"),
|
|
22792
22912
|
// tsx: cli/src/lib/ → ../../../client
|
|
22793
22913
|
...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
|
|
22794
22914
|
];
|
|
22795
22915
|
for (const candidate of candidates2) {
|
|
22796
|
-
if ((0,
|
|
22916
|
+
if ((0, import_node_fs30.existsSync)((0, import_node_path27.join)(candidate, "skills"))) {
|
|
22797
22917
|
return candidate;
|
|
22798
22918
|
}
|
|
22799
22919
|
}
|
|
@@ -22802,13 +22922,13 @@ function resolveDataDir() {
|
|
|
22802
22922
|
);
|
|
22803
22923
|
}
|
|
22804
22924
|
function setupDataPath(file) {
|
|
22805
|
-
return (0,
|
|
22925
|
+
return (0, import_node_path27.join)(resolveDataDir(), "skills", "verity-setup", file);
|
|
22806
22926
|
}
|
|
22807
22927
|
|
|
22808
22928
|
// src/lib/detect.ts
|
|
22809
|
-
var
|
|
22810
|
-
var
|
|
22811
|
-
var
|
|
22929
|
+
var import_node_child_process9 = require("node:child_process");
|
|
22930
|
+
var import_node_fs31 = require("node:fs");
|
|
22931
|
+
var import_node_path28 = require("node:path");
|
|
22812
22932
|
var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
22813
22933
|
"typescript",
|
|
22814
22934
|
"javascript",
|
|
@@ -22845,7 +22965,7 @@ function isIgnored2(path) {
|
|
|
22845
22965
|
}
|
|
22846
22966
|
function listProjectFiles(root) {
|
|
22847
22967
|
try {
|
|
22848
|
-
const out2 = (0,
|
|
22968
|
+
const out2 = (0, import_node_child_process9.execSync)("git ls-files -z", {
|
|
22849
22969
|
cwd: root,
|
|
22850
22970
|
encoding: "utf-8",
|
|
22851
22971
|
maxBuffer: 32 * 1024 * 1024,
|
|
@@ -22865,25 +22985,25 @@ function walk(root) {
|
|
|
22865
22985
|
if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
|
|
22866
22986
|
let entries;
|
|
22867
22987
|
try {
|
|
22868
|
-
entries = (0,
|
|
22988
|
+
entries = (0, import_node_fs31.readdirSync)(dir, { withFileTypes: true });
|
|
22869
22989
|
} catch {
|
|
22870
22990
|
return;
|
|
22871
22991
|
}
|
|
22872
22992
|
for (const entry of entries) {
|
|
22873
22993
|
if (found.length >= WALK_MAX_FILES) return;
|
|
22874
22994
|
if (IGNORED_SEGMENTS.includes(entry.name)) continue;
|
|
22875
|
-
const full = (0,
|
|
22995
|
+
const full = (0, import_node_path28.join)(dir, entry.name);
|
|
22876
22996
|
if (entry.isDirectory()) visit(full, depth + 1);
|
|
22877
|
-
else if (entry.isFile()) found.push((0,
|
|
22997
|
+
else if (entry.isFile()) found.push((0, import_node_path28.relative)(root, full));
|
|
22878
22998
|
}
|
|
22879
22999
|
};
|
|
22880
23000
|
visit(root, 0);
|
|
22881
23001
|
return found;
|
|
22882
23002
|
}
|
|
22883
23003
|
function languageOf(path) {
|
|
22884
|
-
const name2 = (0,
|
|
23004
|
+
const name2 = (0, import_node_path28.basename)(path);
|
|
22885
23005
|
if (/^Dockerfile(\..+)?$/i.test(name2)) return "dockerfile";
|
|
22886
|
-
if (!(0,
|
|
23006
|
+
if (!(0, import_node_path28.extname)(name2)) return null;
|
|
22887
23007
|
const lang = detectLanguage(path);
|
|
22888
23008
|
return lang || null;
|
|
22889
23009
|
}
|
|
@@ -22940,7 +23060,7 @@ var TOOL_CONFIG_MARKERS = [
|
|
|
22940
23060
|
];
|
|
22941
23061
|
function readJson2(path) {
|
|
22942
23062
|
try {
|
|
22943
|
-
return JSON.parse((0,
|
|
23063
|
+
return JSON.parse((0, import_node_fs31.readFileSync)(path, "utf-8"));
|
|
22944
23064
|
} catch {
|
|
22945
23065
|
return null;
|
|
22946
23066
|
}
|
|
@@ -22965,17 +23085,17 @@ function declaredDependencies(root, files) {
|
|
|
22965
23085
|
if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
|
|
22966
23086
|
}
|
|
22967
23087
|
};
|
|
22968
|
-
readPackageJson((0,
|
|
22969
|
-
const nested = files.filter((f) => f.includes("/") && (0,
|
|
22970
|
-
for (const rel of nested) readPackageJson((0,
|
|
23088
|
+
readPackageJson((0, import_node_path28.join)(root, "package.json"));
|
|
23089
|
+
const nested = files.filter((f) => f.includes("/") && (0, import_node_path28.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
|
|
23090
|
+
for (const rel of nested) readPackageJson((0, import_node_path28.join)(root, rel));
|
|
22971
23091
|
const pythonManifests = [
|
|
22972
|
-
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0,
|
|
22973
|
-
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0,
|
|
23092
|
+
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path28.join)(root, f)),
|
|
23093
|
+
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path28.join)(root, f))
|
|
22974
23094
|
];
|
|
22975
23095
|
for (const path of pythonManifests) {
|
|
22976
|
-
if (!(0,
|
|
23096
|
+
if (!(0, import_node_fs31.existsSync)(path)) continue;
|
|
22977
23097
|
try {
|
|
22978
|
-
const text = (0,
|
|
23098
|
+
const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
|
|
22979
23099
|
for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
|
|
22980
23100
|
for (const line2 of text.split("\n")) {
|
|
22981
23101
|
if (!/dependencies\s*=/.test(line2)) continue;
|
|
@@ -22985,13 +23105,13 @@ function declaredDependencies(root, files) {
|
|
|
22985
23105
|
}
|
|
22986
23106
|
}
|
|
22987
23107
|
const goMods = [
|
|
22988
|
-
(0,
|
|
22989
|
-
...files.filter((f) => f.includes("/") && (0,
|
|
23108
|
+
(0, import_node_path28.join)(root, "go.mod"),
|
|
23109
|
+
...files.filter((f) => f.includes("/") && (0, import_node_path28.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path28.join)(root, f))
|
|
22990
23110
|
];
|
|
22991
23111
|
for (const path of goMods) {
|
|
22992
|
-
if (!(0,
|
|
23112
|
+
if (!(0, import_node_fs31.existsSync)(path)) continue;
|
|
22993
23113
|
try {
|
|
22994
|
-
const text = (0,
|
|
23114
|
+
const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
|
|
22995
23115
|
for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
|
|
22996
23116
|
names2.push(m[1].replace(/^github\.com\//, ""));
|
|
22997
23117
|
}
|
|
@@ -22999,10 +23119,10 @@ function declaredDependencies(root, files) {
|
|
|
22999
23119
|
}
|
|
23000
23120
|
}
|
|
23001
23121
|
for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
|
|
23002
|
-
const path = (0,
|
|
23003
|
-
if (!(0,
|
|
23122
|
+
const path = (0, import_node_path28.join)(root, file);
|
|
23123
|
+
if (!(0, import_node_fs31.existsSync)(path)) continue;
|
|
23004
23124
|
try {
|
|
23005
|
-
const text = (0,
|
|
23125
|
+
const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
|
|
23006
23126
|
for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
|
|
23007
23127
|
} catch {
|
|
23008
23128
|
}
|
|
@@ -23010,7 +23130,7 @@ function declaredDependencies(root, files) {
|
|
|
23010
23130
|
return names2;
|
|
23011
23131
|
}
|
|
23012
23132
|
function detectBuildSystem(root, files) {
|
|
23013
|
-
const has = (f) => (0,
|
|
23133
|
+
const has = (f) => (0, import_node_fs31.existsSync)((0, import_node_path28.join)(root, f)) || files.some((p) => (0, import_node_path28.basename)(p) === f);
|
|
23014
23134
|
if (has("pnpm-lock.yaml")) return "pnpm";
|
|
23015
23135
|
if (has("yarn.lock")) return "yarn";
|
|
23016
23136
|
if (has("bun.lock") || has("bun.lockb")) return "bun";
|
|
@@ -23027,8 +23147,8 @@ function detectBuildSystem(root, files) {
|
|
|
23027
23147
|
}
|
|
23028
23148
|
function detectArchitecture(root, files) {
|
|
23029
23149
|
const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
|
|
23030
|
-
if (workspaceMarkers.some((m) => (0,
|
|
23031
|
-
const pkg = readJson2((0,
|
|
23150
|
+
if (workspaceMarkers.some((m) => (0, import_node_fs31.existsSync)((0, import_node_path28.join)(root, m)))) return "monorepo";
|
|
23151
|
+
const pkg = readJson2((0, import_node_path28.join)(root, "package.json"));
|
|
23032
23152
|
if (pkg && "workspaces" in pkg) return "monorepo";
|
|
23033
23153
|
const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
|
|
23034
23154
|
const nested = manifests.filter((f) => f.includes("/"));
|
|
@@ -23050,10 +23170,10 @@ function measureAvgFileLength(root, files, languages) {
|
|
|
23050
23170
|
let total = 0;
|
|
23051
23171
|
let counted = 0;
|
|
23052
23172
|
for (let i2 = 0; i2 < candidates2.length; i2 += stride) {
|
|
23053
|
-
const path = (0,
|
|
23173
|
+
const path = (0, import_node_path28.join)(root, candidates2[i2]);
|
|
23054
23174
|
try {
|
|
23055
|
-
if ((0,
|
|
23056
|
-
total += (0,
|
|
23175
|
+
if ((0, import_node_fs31.statSync)(path).size > 2 * 1024 * 1024) continue;
|
|
23176
|
+
total += (0, import_node_fs31.readFileSync)(path, "utf-8").split("\n").length;
|
|
23057
23177
|
counted++;
|
|
23058
23178
|
} catch {
|
|
23059
23179
|
}
|
|
@@ -23083,14 +23203,14 @@ function detectProject(root = repoRoot()) {
|
|
|
23083
23203
|
const existingToolConfigs = [];
|
|
23084
23204
|
for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
|
|
23085
23205
|
for (const marker of markers) {
|
|
23086
|
-
if ((0,
|
|
23206
|
+
if ((0, import_node_fs31.existsSync)((0, import_node_path28.join)(root, marker))) {
|
|
23087
23207
|
existingToolConfigs.push({ tool, path: `./${marker}` });
|
|
23088
23208
|
break;
|
|
23089
23209
|
}
|
|
23090
23210
|
}
|
|
23091
23211
|
}
|
|
23092
23212
|
return {
|
|
23093
|
-
projectName: (0,
|
|
23213
|
+
projectName: (0, import_node_path28.basename)(root),
|
|
23094
23214
|
languages,
|
|
23095
23215
|
languageCounts,
|
|
23096
23216
|
frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
|
|
@@ -23188,8 +23308,8 @@ ${closingNote(input.origin)}
|
|
|
23188
23308
|
|
|
23189
23309
|
// src/lib/synthesize.ts
|
|
23190
23310
|
function loadCatalog() {
|
|
23191
|
-
const catalog = (0, import_yaml.parse)((0,
|
|
23192
|
-
const template = (0, import_yaml.parse)((0,
|
|
23311
|
+
const catalog = (0, import_yaml.parse)((0, import_node_fs32.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
|
|
23312
|
+
const template = (0, import_yaml.parse)((0, import_node_fs32.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
|
|
23193
23313
|
return { catalog, template };
|
|
23194
23314
|
}
|
|
23195
23315
|
function selectTools(languages, intensity, catalog) {
|
|
@@ -23240,7 +23360,7 @@ var TRIVY_BY_INTENSITY = {
|
|
|
23240
23360
|
};
|
|
23241
23361
|
function adapterPatternIds(toolId) {
|
|
23242
23362
|
try {
|
|
23243
|
-
const out2 = (0,
|
|
23363
|
+
const out2 = (0, import_node_child_process10.execFileSync)(
|
|
23244
23364
|
process.execPath,
|
|
23245
23365
|
[setupDataPath("validate-patterns.mjs"), "--list", toolId],
|
|
23246
23366
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }
|
|
@@ -23270,7 +23390,7 @@ function resolvePatternId(toolId, curatedId, adapterIds) {
|
|
|
23270
23390
|
}
|
|
23271
23391
|
function trivyPatterns(intensity) {
|
|
23272
23392
|
try {
|
|
23273
|
-
const out2 = (0,
|
|
23393
|
+
const out2 = (0, import_node_child_process10.execFileSync)(
|
|
23274
23394
|
process.execPath,
|
|
23275
23395
|
[setupDataPath("validate-patterns.mjs"), "--emit", "Trivy", TRIVY_BY_INTENSITY[intensity].emit],
|
|
23276
23396
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }
|
|
@@ -23450,7 +23570,7 @@ export default tseslint.config(
|
|
|
23450
23570
|
function validatePatternIds() {
|
|
23451
23571
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
23452
23572
|
try {
|
|
23453
|
-
(0,
|
|
23573
|
+
(0, import_node_child_process10.execFileSync)(process.execPath, [setupDataPath("validate-patterns.mjs"), configPath], {
|
|
23454
23574
|
encoding: "utf-8",
|
|
23455
23575
|
stdio: ["pipe", "pipe", "pipe"],
|
|
23456
23576
|
timeout: 6e4
|
|
@@ -23467,7 +23587,7 @@ function validatePatternIds() {
|
|
|
23467
23587
|
}
|
|
23468
23588
|
async function runSynthesis(opts) {
|
|
23469
23589
|
const standardPath = projectPath(STANDARD_FILE);
|
|
23470
|
-
if ((0,
|
|
23590
|
+
if ((0, import_node_fs32.existsSync)(standardPath) && !opts.force) {
|
|
23471
23591
|
return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
|
|
23472
23592
|
}
|
|
23473
23593
|
const detected = opts.detected ?? detectProject();
|
|
@@ -23536,7 +23656,7 @@ async function correctVerityMdVersion(opts) {
|
|
|
23536
23656
|
}
|
|
23537
23657
|
async function writeFileTo(relative6, body2) {
|
|
23538
23658
|
const target = projectPath(relative6);
|
|
23539
|
-
await (0, import_promises10.mkdir)((0,
|
|
23659
|
+
await (0, import_promises10.mkdir)((0, import_node_path29.dirname)(target), { recursive: true });
|
|
23540
23660
|
await (0, import_promises10.writeFile)(target, body2);
|
|
23541
23661
|
}
|
|
23542
23662
|
async function deriveConfigForStandard(standard) {
|
|
@@ -23595,11 +23715,11 @@ ${validation.detail}`);
|
|
|
23595
23715
|
|
|
23596
23716
|
// src/lib/setup-state.ts
|
|
23597
23717
|
var import_promises11 = require("node:fs/promises");
|
|
23598
|
-
var
|
|
23718
|
+
var import_node_fs33 = require("node:fs");
|
|
23599
23719
|
var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
|
|
23600
23720
|
async function readSetupState() {
|
|
23601
23721
|
const path = projectPath(SETUP_STATE_FILE);
|
|
23602
|
-
if (!(0,
|
|
23722
|
+
if (!(0, import_node_fs33.existsSync)(path)) return null;
|
|
23603
23723
|
try {
|
|
23604
23724
|
const parsed = JSON.parse(await (0, import_promises11.readFile)(path, "utf-8"));
|
|
23605
23725
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
@@ -23615,12 +23735,12 @@ async function writeSetupState(patch) {
|
|
|
23615
23735
|
}
|
|
23616
23736
|
|
|
23617
23737
|
// src/lib/push-setup.ts
|
|
23618
|
-
var
|
|
23738
|
+
var import_node_fs35 = require("node:fs");
|
|
23619
23739
|
var import_promises12 = require("node:fs/promises");
|
|
23620
23740
|
var import_yaml2 = __toESM2(require_dist());
|
|
23621
23741
|
|
|
23622
23742
|
// src/lib/verityignore.ts
|
|
23623
|
-
var
|
|
23743
|
+
var import_node_fs34 = require("node:fs");
|
|
23624
23744
|
var EMPTY = { rules: [], securityOverlap: [], problems: [] };
|
|
23625
23745
|
var SECURITY_PROBES = [
|
|
23626
23746
|
".env",
|
|
@@ -23713,9 +23833,9 @@ function isIgnored3(ig, path) {
|
|
|
23713
23833
|
}
|
|
23714
23834
|
function loadVerityIgnore() {
|
|
23715
23835
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
23716
|
-
if (!(0,
|
|
23836
|
+
if (!(0, import_node_fs34.existsSync)(file)) return EMPTY;
|
|
23717
23837
|
try {
|
|
23718
|
-
return parseVerityIgnore((0,
|
|
23838
|
+
return parseVerityIgnore((0, import_node_fs34.readFileSync)(file, "utf-8"));
|
|
23719
23839
|
} catch {
|
|
23720
23840
|
return EMPTY;
|
|
23721
23841
|
}
|
|
@@ -23753,9 +23873,9 @@ function buildStandardUpload(standard, ignoreRaw) {
|
|
|
23753
23873
|
}
|
|
23754
23874
|
function readVerityIgnoreRaw() {
|
|
23755
23875
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
23756
|
-
if (!(0,
|
|
23876
|
+
if (!(0, import_node_fs34.existsSync)(file)) return null;
|
|
23757
23877
|
try {
|
|
23758
|
-
return (0,
|
|
23878
|
+
return (0, import_node_fs34.readFileSync)(file, "utf-8");
|
|
23759
23879
|
} catch {
|
|
23760
23880
|
return null;
|
|
23761
23881
|
}
|
|
@@ -23783,7 +23903,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
23783
23903
|
}
|
|
23784
23904
|
let standardVersion = null;
|
|
23785
23905
|
const standardPath = projectPath(STANDARD_FILE);
|
|
23786
|
-
if (pushStandard && (0,
|
|
23906
|
+
if (pushStandard && (0, import_node_fs35.existsSync)(standardPath)) {
|
|
23787
23907
|
try {
|
|
23788
23908
|
const content = (0, import_yaml2.parse)(await (0, import_promises12.readFile)(standardPath, "utf-8"));
|
|
23789
23909
|
const upload = buildStandardUpload(content, readVerityIgnoreRaw());
|
|
@@ -23808,7 +23928,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
23808
23928
|
}
|
|
23809
23929
|
let configPushed = false;
|
|
23810
23930
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
23811
|
-
if (pushConfig && (0,
|
|
23931
|
+
if (pushConfig && (0, import_node_fs35.existsSync)(configPath)) {
|
|
23812
23932
|
try {
|
|
23813
23933
|
const content = JSON.parse(await (0, import_promises12.readFile)(configPath, "utf-8"));
|
|
23814
23934
|
const result = await apiRequest({
|
|
@@ -23840,7 +23960,7 @@ function registerStandardCommands(program2) {
|
|
|
23840
23960
|
const state = await readSetupState();
|
|
23841
23961
|
if (opts.configOnly) {
|
|
23842
23962
|
const standardPath = projectPath(STANDARD_FILE);
|
|
23843
|
-
if (!(0,
|
|
23963
|
+
if (!(0, import_node_fs36.existsSync)(standardPath)) {
|
|
23844
23964
|
printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
|
|
23845
23965
|
process.exit(1);
|
|
23846
23966
|
}
|
|
@@ -24031,14 +24151,21 @@ function registerConfigCommands(program2) {
|
|
|
24031
24151
|
});
|
|
24032
24152
|
config.command("formal [state]").description('Get or set formal verification at push: "push" or "off" (needs Lean \u2014 verity lean status)').action((state) => {
|
|
24033
24153
|
if (state === void 0) {
|
|
24034
|
-
|
|
24154
|
+
const cfg = readProjectConfig();
|
|
24155
|
+
process.stdout.write((cfg.formal === "push" ? "push" : "off") + "\n");
|
|
24156
|
+
if (cfg.formal_refused) printWarn(formalRefusalMessage(cfg.formal_refused));
|
|
24035
24157
|
return;
|
|
24036
24158
|
}
|
|
24037
24159
|
if (state !== "push" && state !== "off") {
|
|
24038
24160
|
printError(`Unrecognised state: ${state}. Use "push" or "off".`);
|
|
24039
24161
|
process.exit(1);
|
|
24040
24162
|
}
|
|
24041
|
-
writeProjectConfig({ formal: state === "push" ? "push" :
|
|
24163
|
+
writeProjectConfig({ formal: state === "push" ? "push" : "off" });
|
|
24164
|
+
const refused2 = state === "push" ? readProjectConfig().formal_refused : void 0;
|
|
24165
|
+
if (refused2) {
|
|
24166
|
+
printWarn(`Formal verification at push: still off \u2014 ${formalRefusalMessage(refused2)}`);
|
|
24167
|
+
return;
|
|
24168
|
+
}
|
|
24042
24169
|
printInfo(state === "push" ? "Formal verification at push: on for this checkout (Lean must be installed \u2014 verity lean status)" : "Formal verification at push: off");
|
|
24043
24170
|
if (state === "push") printInfo("The phase runs with your Verity login (a push without one is skipped and says so: not-logged-in)");
|
|
24044
24171
|
});
|
|
@@ -24186,10 +24313,10 @@ function formatRunDetail(run4) {
|
|
|
24186
24313
|
}
|
|
24187
24314
|
|
|
24188
24315
|
// src/lib/ignore-declaration.ts
|
|
24189
|
-
var
|
|
24316
|
+
var import_node_fs38 = require("node:fs");
|
|
24190
24317
|
|
|
24191
24318
|
// src/lib/debounce.ts
|
|
24192
|
-
var
|
|
24319
|
+
var import_node_fs37 = require("node:fs");
|
|
24193
24320
|
var import_node_crypto11 = require("node:crypto");
|
|
24194
24321
|
function scopedFile(base, sessionId) {
|
|
24195
24322
|
if (!sessionId) return base;
|
|
@@ -24197,9 +24324,9 @@ function scopedFile(base, sessionId) {
|
|
|
24197
24324
|
}
|
|
24198
24325
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
24199
24326
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
24200
|
-
if (!(0,
|
|
24327
|
+
if (!(0, import_node_fs37.existsSync)(file)) return null;
|
|
24201
24328
|
try {
|
|
24202
|
-
const lastTs = parseInt((0,
|
|
24329
|
+
const lastTs = parseInt((0, import_node_fs37.readFileSync)(file, "utf-8").trim(), 10);
|
|
24203
24330
|
const nowTs = Math.floor(Date.now() / 1e3);
|
|
24204
24331
|
const elapsed = nowTs - lastTs;
|
|
24205
24332
|
if (elapsed < debounceSeconds) {
|
|
@@ -24212,10 +24339,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
|
24212
24339
|
function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
24213
24340
|
if (bypassForRecentCommits) return null;
|
|
24214
24341
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
24215
|
-
if (!(0,
|
|
24342
|
+
if (!(0, import_node_fs37.existsSync)(file)) return null;
|
|
24216
24343
|
let debounceTime;
|
|
24217
24344
|
try {
|
|
24218
|
-
debounceTime = (0,
|
|
24345
|
+
debounceTime = (0, import_node_fs37.statSync)(file).mtimeMs;
|
|
24219
24346
|
} catch {
|
|
24220
24347
|
return null;
|
|
24221
24348
|
}
|
|
@@ -24223,7 +24350,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
24223
24350
|
const resolved = resolveFile(f);
|
|
24224
24351
|
if (!resolved) continue;
|
|
24225
24352
|
try {
|
|
24226
|
-
const stat3 = (0,
|
|
24353
|
+
const stat3 = (0, import_node_fs37.statSync)(resolved);
|
|
24227
24354
|
if (stat3.mtimeMs > debounceTime) {
|
|
24228
24355
|
return null;
|
|
24229
24356
|
}
|
|
@@ -24239,8 +24366,8 @@ function computeContentHash(files) {
|
|
|
24239
24366
|
for (const f of sorted) {
|
|
24240
24367
|
const resolved = resolveFile(f) ?? f;
|
|
24241
24368
|
try {
|
|
24242
|
-
if ((0,
|
|
24243
|
-
hash.update((0,
|
|
24369
|
+
if ((0, import_node_fs37.existsSync)(resolved)) {
|
|
24370
|
+
hash.update((0, import_node_fs37.readFileSync)(resolved));
|
|
24244
24371
|
}
|
|
24245
24372
|
} catch {
|
|
24246
24373
|
}
|
|
@@ -24250,9 +24377,9 @@ function computeContentHash(files) {
|
|
|
24250
24377
|
function checkContentHash(files, sessionId) {
|
|
24251
24378
|
const hash = computeContentHash(files);
|
|
24252
24379
|
const file = scopedFile(HASH_FILE, sessionId);
|
|
24253
|
-
if ((0,
|
|
24380
|
+
if ((0, import_node_fs37.existsSync)(file)) {
|
|
24254
24381
|
try {
|
|
24255
|
-
const storedHash = (0,
|
|
24382
|
+
const storedHash = (0, import_node_fs37.readFileSync)(file, "utf-8").trim();
|
|
24256
24383
|
if (hash === storedHash) {
|
|
24257
24384
|
return { skip: "No source changes since last analysis", hash };
|
|
24258
24385
|
}
|
|
@@ -24262,24 +24389,24 @@ function checkContentHash(files, sessionId) {
|
|
|
24262
24389
|
return { skip: null, hash };
|
|
24263
24390
|
}
|
|
24264
24391
|
function recordAnalysisStart(sessionId) {
|
|
24265
|
-
(0,
|
|
24266
|
-
(0,
|
|
24392
|
+
(0, import_node_fs37.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
24393
|
+
(0, import_node_fs37.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
|
|
24267
24394
|
}
|
|
24268
24395
|
function recordPassHash(hash, sessionId) {
|
|
24269
|
-
(0,
|
|
24396
|
+
(0, import_node_fs37.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
|
|
24270
24397
|
}
|
|
24271
24398
|
function narrowToRecent(files, sessionId) {
|
|
24272
24399
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
24273
|
-
if (!(0,
|
|
24400
|
+
if (!(0, import_node_fs37.existsSync)(file)) return files;
|
|
24274
24401
|
let debounceTime;
|
|
24275
24402
|
try {
|
|
24276
|
-
debounceTime = (0,
|
|
24403
|
+
debounceTime = (0, import_node_fs37.statSync)(file).mtimeMs;
|
|
24277
24404
|
} catch {
|
|
24278
24405
|
return files;
|
|
24279
24406
|
}
|
|
24280
24407
|
const recent = files.filter((f) => {
|
|
24281
24408
|
try {
|
|
24282
|
-
return (0,
|
|
24409
|
+
return (0, import_node_fs37.existsSync)(f) && (0, import_node_fs37.statSync)(f).mtimeMs > debounceTime;
|
|
24283
24410
|
} catch {
|
|
24284
24411
|
return false;
|
|
24285
24412
|
}
|
|
@@ -24292,9 +24419,9 @@ function readIteration(currentCommit, _contentHash) {
|
|
|
24292
24419
|
var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
|
|
24293
24420
|
function readBlockState(currentCommit, opts) {
|
|
24294
24421
|
if (opts?.newUserPrompt) return NO_BLOCKS;
|
|
24295
|
-
if (!(0,
|
|
24422
|
+
if (!(0, import_node_fs37.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
|
|
24296
24423
|
try {
|
|
24297
|
-
const stored = (0,
|
|
24424
|
+
const stored = (0, import_node_fs37.readFileSync)(ITERATION_FILE, "utf-8").trim();
|
|
24298
24425
|
const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
|
|
24299
24426
|
if (!parsed) return NO_BLOCKS;
|
|
24300
24427
|
if (parsed.commit !== currentCommit) return NO_BLOCKS;
|
|
@@ -24340,8 +24467,8 @@ function isSameProblem(previous, current) {
|
|
|
24340
24467
|
return current.split(",").some((k) => prev.has(k));
|
|
24341
24468
|
}
|
|
24342
24469
|
function writeBlockState(commit, state) {
|
|
24343
|
-
(0,
|
|
24344
|
-
(0,
|
|
24470
|
+
(0, import_node_fs37.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
24471
|
+
(0, import_node_fs37.writeFileSync)(
|
|
24345
24472
|
ITERATION_FILE,
|
|
24346
24473
|
JSON.stringify({
|
|
24347
24474
|
v: 2,
|
|
@@ -24446,9 +24573,9 @@ function resolveIgnoreState(keys) {
|
|
|
24446
24573
|
}
|
|
24447
24574
|
function readIgnoreState(sessionId) {
|
|
24448
24575
|
const file = stateFile(sessionId);
|
|
24449
|
-
if (!(0,
|
|
24576
|
+
if (!(0, import_node_fs38.existsSync)(file)) return null;
|
|
24450
24577
|
try {
|
|
24451
|
-
const o = JSON.parse((0,
|
|
24578
|
+
const o = JSON.parse((0, import_node_fs38.readFileSync)(file, "utf-8")) ?? {};
|
|
24452
24579
|
const spent = typeof o.spent === "number" ? o.spent : 0;
|
|
24453
24580
|
const raw = o.active;
|
|
24454
24581
|
let active = null;
|
|
@@ -24472,8 +24599,8 @@ function readIgnoreState(sessionId) {
|
|
|
24472
24599
|
}
|
|
24473
24600
|
function writeIgnoreState(state, sessionId) {
|
|
24474
24601
|
try {
|
|
24475
|
-
(0,
|
|
24476
|
-
(0,
|
|
24602
|
+
(0, import_node_fs38.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
24603
|
+
(0, import_node_fs38.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
|
|
24477
24604
|
} catch {
|
|
24478
24605
|
}
|
|
24479
24606
|
}
|
|
@@ -24856,85 +24983,10 @@ function createRun(opts, globals) {
|
|
|
24856
24983
|
}
|
|
24857
24984
|
|
|
24858
24985
|
// src/commands/analyze/index.ts
|
|
24859
|
-
var
|
|
24986
|
+
var import_node_fs52 = require("node:fs");
|
|
24860
24987
|
|
|
24861
24988
|
// src/lib/repo-context.ts
|
|
24862
24989
|
var import_node_child_process11 = require("node:child_process");
|
|
24863
|
-
|
|
24864
|
-
// src/lib/hardened-git.ts
|
|
24865
|
-
var import_node_child_process10 = require("node:child_process");
|
|
24866
|
-
var HARDENED_CONFIG_ARGS = [
|
|
24867
|
-
"-c",
|
|
24868
|
-
"core.fsmonitor=false",
|
|
24869
|
-
"-c",
|
|
24870
|
-
"core.pager=cat",
|
|
24871
|
-
"-c",
|
|
24872
|
-
"log.showSignature=false"
|
|
24873
|
-
];
|
|
24874
|
-
var DIFF_READ_FLAGS = ["--no-ext-diff", "--no-textconv"];
|
|
24875
|
-
var DEFAULT_GIT_TIMEOUT_MS = 6e4;
|
|
24876
|
-
var DEFAULT_GIT_MAX_BUFFER = 64 * 1024 * 1024;
|
|
24877
|
-
function hardenedGitEnv(base = process.env) {
|
|
24878
|
-
const env = {};
|
|
24879
|
-
for (const [key, value] of Object.entries(base)) {
|
|
24880
|
-
if (key.startsWith("GIT_")) continue;
|
|
24881
|
-
env[key] = value;
|
|
24882
|
-
}
|
|
24883
|
-
env.GIT_OPTIONAL_LOCKS = "0";
|
|
24884
|
-
env.GIT_TERMINAL_PROMPT = "0";
|
|
24885
|
-
return env;
|
|
24886
|
-
}
|
|
24887
|
-
function hardenedGitArgv(args2) {
|
|
24888
|
-
return [...HARDENED_CONFIG_ARGS, ...args2];
|
|
24889
|
-
}
|
|
24890
|
-
function classifyError(err2) {
|
|
24891
|
-
const e = err2;
|
|
24892
|
-
const stderr = typeof e?.stderr === "string" ? e.stderr : e?.stderr ? e.stderr.toString("utf-8") : "";
|
|
24893
|
-
if (e?.code === "ETIMEDOUT" || e?.killed && e?.signal === "SIGTERM") return { ok: false, error: "timeout", stderr };
|
|
24894
|
-
if (e?.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") return { ok: false, error: "too_large", stderr };
|
|
24895
|
-
return { ok: false, error: "failed", stderr };
|
|
24896
|
-
}
|
|
24897
|
-
function runGitSync(cwd, args2, opts = {}) {
|
|
24898
|
-
try {
|
|
24899
|
-
const stdout = (0, import_node_child_process10.execFileSync)("git", hardenedGitArgv(args2), {
|
|
24900
|
-
cwd,
|
|
24901
|
-
env: hardenedGitEnv(),
|
|
24902
|
-
encoding: "utf-8",
|
|
24903
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
24904
|
-
timeout: opts.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS,
|
|
24905
|
-
maxBuffer: opts.maxBuffer ?? DEFAULT_GIT_MAX_BUFFER
|
|
24906
|
-
});
|
|
24907
|
-
return { ok: true, stdout };
|
|
24908
|
-
} catch (err2) {
|
|
24909
|
-
return classifyError(err2);
|
|
24910
|
-
}
|
|
24911
|
-
}
|
|
24912
|
-
function runGit(cwd, args2, opts = {}) {
|
|
24913
|
-
return new Promise((resolvePromise) => {
|
|
24914
|
-
(0, import_node_child_process10.execFile)(
|
|
24915
|
-
"git",
|
|
24916
|
-
hardenedGitArgv(args2),
|
|
24917
|
-
{
|
|
24918
|
-
cwd,
|
|
24919
|
-
env: hardenedGitEnv(),
|
|
24920
|
-
encoding: "utf-8",
|
|
24921
|
-
timeout: opts.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS,
|
|
24922
|
-
maxBuffer: opts.maxBuffer ?? DEFAULT_GIT_MAX_BUFFER
|
|
24923
|
-
},
|
|
24924
|
-
(err2, stdout, stderr) => {
|
|
24925
|
-
if (err2) {
|
|
24926
|
-
const e = err2;
|
|
24927
|
-
e.stderr = stderr;
|
|
24928
|
-
resolvePromise(classifyError(e));
|
|
24929
|
-
return;
|
|
24930
|
-
}
|
|
24931
|
-
resolvePromise({ ok: true, stdout });
|
|
24932
|
-
}
|
|
24933
|
-
);
|
|
24934
|
-
});
|
|
24935
|
-
}
|
|
24936
|
-
|
|
24937
|
-
// src/lib/repo-context.ts
|
|
24938
24990
|
var import_node_os5 = require("node:os");
|
|
24939
24991
|
function rgInvocations(env = process.env) {
|
|
24940
24992
|
const out2 = [{ cmd: "rg" }];
|
|
@@ -25895,10 +25947,10 @@ function installRunEvidence(run4) {
|
|
|
25895
25947
|
}
|
|
25896
25948
|
|
|
25897
25949
|
// src/lib/git-frame.ts
|
|
25898
|
-
var
|
|
25950
|
+
var import_node_fs39 = require("node:fs");
|
|
25899
25951
|
var import_node_os6 = require("node:os");
|
|
25900
|
-
var import_node_path29 = require("node:path");
|
|
25901
25952
|
var import_node_path30 = require("node:path");
|
|
25953
|
+
var import_node_path31 = require("node:path");
|
|
25902
25954
|
var VALUE_TOKEN = `(?:'[^']*'|"[^"]*"|\\S+)`;
|
|
25903
25955
|
var GIT_GLOBAL_OPTS = `(?:\\s+(?:-[Cc]\\s+${VALUE_TOKEN}|--?[\\w-]+(?:=\\S+)?))*`;
|
|
25904
25956
|
var COMMIT_HEAD = `git${GIT_GLOBAL_OPTS}\\s+commit(?![\\w-])`;
|
|
@@ -25985,8 +26037,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
25985
26037
|
if (SHELL_DYNAMIC.test(raw) || raw === "-") {
|
|
25986
26038
|
return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
|
|
25987
26039
|
}
|
|
25988
|
-
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0,
|
|
25989
|
-
dir = (0,
|
|
26040
|
+
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path31.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
|
|
26041
|
+
dir = (0, import_node_path30.isAbsolute)(expanded) ? expanded : (0, import_node_path30.resolve)(dir, expanded);
|
|
25990
26042
|
}
|
|
25991
26043
|
const seg = segments[segmentIndex];
|
|
25992
26044
|
const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
|
|
@@ -26004,8 +26056,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
26004
26056
|
if (SHELL_DYNAMIC.test(raw)) {
|
|
26005
26057
|
return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
|
|
26006
26058
|
}
|
|
26007
|
-
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0,
|
|
26008
|
-
dir = (0,
|
|
26059
|
+
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path31.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
|
|
26060
|
+
dir = (0, import_node_path30.isAbsolute)(expanded) ? expanded : (0, import_node_path30.resolve)(dir, expanded);
|
|
26009
26061
|
}
|
|
26010
26062
|
}
|
|
26011
26063
|
return { dir, named, unresolvable: null };
|
|
@@ -26065,14 +26117,14 @@ function gitAt(dir, args2) {
|
|
|
26065
26117
|
}
|
|
26066
26118
|
function realpathOr2(p) {
|
|
26067
26119
|
try {
|
|
26068
|
-
return
|
|
26120
|
+
return import_node_fs39.realpathSync.native(p);
|
|
26069
26121
|
} catch {
|
|
26070
|
-
return (0,
|
|
26122
|
+
return (0, import_node_path30.resolve)(p);
|
|
26071
26123
|
}
|
|
26072
26124
|
}
|
|
26073
26125
|
function resolveFrame(input) {
|
|
26074
26126
|
const found = findMomentSegment(input.command, input.on);
|
|
26075
|
-
const hookDirUsable = !!input.hookCwd && (0,
|
|
26127
|
+
const hookDirUsable = !!input.hookCwd && (0, import_node_fs39.existsSync)(input.hookCwd);
|
|
26076
26128
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
26077
26129
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
26078
26130
|
const refuse = (refusal) => ({
|
|
@@ -26095,7 +26147,7 @@ function resolveFrame(input) {
|
|
|
26095
26147
|
if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
|
|
26096
26148
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
26097
26149
|
if (targetDir !== baseDir) {
|
|
26098
|
-
if (!(0,
|
|
26150
|
+
if (!(0, import_node_fs39.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
|
|
26099
26151
|
dir = targetDir;
|
|
26100
26152
|
}
|
|
26101
26153
|
}
|
|
@@ -26106,7 +26158,7 @@ function resolveFrame(input) {
|
|
|
26106
26158
|
const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
|
|
26107
26159
|
const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
|
|
26108
26160
|
const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
|
|
26109
|
-
const commonDir = commonRaw ? realpathOr2((0,
|
|
26161
|
+
const commonDir = commonRaw ? realpathOr2((0, import_node_path30.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path30.resolve)(dir, commonRaw)) : null;
|
|
26110
26162
|
const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
26111
26163
|
return {
|
|
26112
26164
|
moment: found?.moment ?? null,
|
|
@@ -26281,8 +26333,8 @@ function stagedRange(frame, command) {
|
|
|
26281
26333
|
if (plan.kind === "unpredictable") {
|
|
26282
26334
|
return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
|
|
26283
26335
|
}
|
|
26284
|
-
const mergeHead = frame.gitDir ? (0,
|
|
26285
|
-
if (mergeHead && (0,
|
|
26336
|
+
const mergeHead = frame.gitDir ? (0, import_node_path31.join)(frame.gitDir, "MERGE_HEAD") : null;
|
|
26337
|
+
if (mergeHead && (0, import_node_fs39.existsSync)(mergeHead)) {
|
|
26286
26338
|
const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
|
|
26287
26339
|
const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
|
|
26288
26340
|
const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
|
|
@@ -26416,7 +26468,7 @@ function truthy(v) {
|
|
|
26416
26468
|
}
|
|
26417
26469
|
|
|
26418
26470
|
// src/lib/transcript.ts
|
|
26419
|
-
var
|
|
26471
|
+
var import_node_fs40 = require("node:fs");
|
|
26420
26472
|
var MAX_READ_BYTES = 256 * 1024;
|
|
26421
26473
|
var SMALL_FILE_BYTES = 64 * 1024;
|
|
26422
26474
|
var MAX_FILES_LIST = 20;
|
|
@@ -26443,7 +26495,7 @@ async function extractActionSummary(transcriptPath) {
|
|
|
26443
26495
|
function readTurnLines(transcriptPath) {
|
|
26444
26496
|
let size;
|
|
26445
26497
|
try {
|
|
26446
|
-
size = (0,
|
|
26498
|
+
size = (0, import_node_fs40.statSync)(transcriptPath).size;
|
|
26447
26499
|
} catch {
|
|
26448
26500
|
return null;
|
|
26449
26501
|
}
|
|
@@ -26451,7 +26503,7 @@ function readTurnLines(transcriptPath) {
|
|
|
26451
26503
|
let raw;
|
|
26452
26504
|
let windowed = false;
|
|
26453
26505
|
if (size <= SMALL_FILE_BYTES) {
|
|
26454
|
-
raw = (0,
|
|
26506
|
+
raw = (0, import_node_fs40.readFileSync)(transcriptPath, "utf-8");
|
|
26455
26507
|
} else {
|
|
26456
26508
|
windowed = true;
|
|
26457
26509
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
@@ -27021,7 +27073,7 @@ function channelSilence(input) {
|
|
|
27021
27073
|
// src/lib/cli-version.ts
|
|
27022
27074
|
function cliVersion() {
|
|
27023
27075
|
try {
|
|
27024
|
-
return true ? "0.34.0-experimental.
|
|
27076
|
+
return true ? "0.34.0-experimental.37a6dcf" : "dev";
|
|
27025
27077
|
} catch {
|
|
27026
27078
|
return "dev";
|
|
27027
27079
|
}
|
|
@@ -27062,7 +27114,7 @@ async function sendSkipBeacon(ctx, reason) {
|
|
|
27062
27114
|
|
|
27063
27115
|
// src/lib/static-analysis.ts
|
|
27064
27116
|
var import_node_child_process12 = require("node:child_process");
|
|
27065
|
-
var
|
|
27117
|
+
var import_node_fs41 = require("node:fs");
|
|
27066
27118
|
var SEVERITY_ORDER = {
|
|
27067
27119
|
Error: 0,
|
|
27068
27120
|
Critical: 0,
|
|
@@ -27118,7 +27170,7 @@ function runCodacyAnalysis(files) {
|
|
|
27118
27170
|
if (files.length === 0) return empty;
|
|
27119
27171
|
const existingFiles = files.filter((f) => {
|
|
27120
27172
|
try {
|
|
27121
|
-
return (0,
|
|
27173
|
+
return (0, import_node_fs41.existsSync)(f);
|
|
27122
27174
|
} catch {
|
|
27123
27175
|
return false;
|
|
27124
27176
|
}
|
|
@@ -27387,8 +27439,8 @@ async function scope(run4) {
|
|
|
27387
27439
|
}
|
|
27388
27440
|
|
|
27389
27441
|
// src/lib/specs.ts
|
|
27390
|
-
var
|
|
27391
|
-
var
|
|
27442
|
+
var import_node_fs42 = require("node:fs");
|
|
27443
|
+
var import_node_path32 = require("node:path");
|
|
27392
27444
|
var SPEC_CANDIDATES = [
|
|
27393
27445
|
"CLAUDE.md",
|
|
27394
27446
|
"AGENTS.md",
|
|
@@ -27410,7 +27462,7 @@ var UNCONSULTED_TOTAL_BYTES = 30720;
|
|
|
27410
27462
|
function readSpecFiles(specsOpt, root) {
|
|
27411
27463
|
const out2 = [];
|
|
27412
27464
|
for (const raw of specsOpt.split(",").map((f) => f.trim()).filter(Boolean)) {
|
|
27413
|
-
const candidate = (0,
|
|
27465
|
+
const candidate = (0, import_node_path32.isAbsolute)(raw) ? (0, import_node_path32.relative)(root, raw) : raw;
|
|
27414
27466
|
const content = readFileInside(root, candidate, MAX_EXPLICIT_SPEC_FILE_BYTES);
|
|
27415
27467
|
if (content === null) continue;
|
|
27416
27468
|
out2.push({ path: raw, content });
|
|
@@ -27429,7 +27481,7 @@ function discoverSpecs(consulted = []) {
|
|
|
27429
27481
|
const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
|
|
27430
27482
|
if (totalBytes >= totalCap) return false;
|
|
27431
27483
|
if (seen.has(specPath)) return true;
|
|
27432
|
-
if (!(0,
|
|
27484
|
+
if (!(0, import_node_fs42.existsSync)(specPath)) return true;
|
|
27433
27485
|
seen.add(specPath);
|
|
27434
27486
|
const remaining = totalCap - totalBytes;
|
|
27435
27487
|
const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
|
|
@@ -27452,7 +27504,7 @@ function discoverSpecs(consulted = []) {
|
|
|
27452
27504
|
if (!addSpec(candidate)) break;
|
|
27453
27505
|
}
|
|
27454
27506
|
for (const dir of ["spec", "docs"]) {
|
|
27455
|
-
if (!(0,
|
|
27507
|
+
if (!(0, import_node_fs42.existsSync)(dir)) continue;
|
|
27456
27508
|
try {
|
|
27457
27509
|
const mdFiles = findMdFiles(dir, 2).sort();
|
|
27458
27510
|
for (const mdFile of mdFiles) {
|
|
@@ -27467,9 +27519,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
27467
27519
|
if (depth >= maxDepth) return [];
|
|
27468
27520
|
const result = [];
|
|
27469
27521
|
try {
|
|
27470
|
-
const entries = (0,
|
|
27522
|
+
const entries = (0, import_node_fs42.readdirSync)(dir, { withFileTypes: true });
|
|
27471
27523
|
for (const entry of entries) {
|
|
27472
|
-
const fullPath = (0,
|
|
27524
|
+
const fullPath = (0, import_node_path32.join)(dir, entry.name);
|
|
27473
27525
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
27474
27526
|
result.push(fullPath);
|
|
27475
27527
|
} else if (entry.isDirectory() && depth < maxDepth - 1) {
|
|
@@ -27482,25 +27534,25 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
27482
27534
|
}
|
|
27483
27535
|
function discoverPlans() {
|
|
27484
27536
|
const home = process.env.HOME ?? "";
|
|
27485
|
-
const homePlansDir = (0,
|
|
27537
|
+
const homePlansDir = (0, import_node_path32.join)(home, ".claude", "plans");
|
|
27486
27538
|
const sources = [];
|
|
27487
27539
|
if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
|
|
27488
|
-
sources.push({ root: process.cwd(), prefix: (0,
|
|
27540
|
+
sources.push({ root: process.cwd(), prefix: (0, import_node_path32.join)(".claude", "plans") });
|
|
27489
27541
|
}
|
|
27490
|
-
if (home && (0,
|
|
27542
|
+
if (home && (0, import_node_fs42.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
|
|
27491
27543
|
const candidates2 = [];
|
|
27492
27544
|
const seen = /* @__PURE__ */ new Set();
|
|
27493
27545
|
for (const source2 of sources) {
|
|
27494
27546
|
let names2;
|
|
27495
27547
|
try {
|
|
27496
|
-
names2 = (0,
|
|
27548
|
+
names2 = (0, import_node_fs42.readdirSync)(source2.prefix ? (0, import_node_path32.join)(source2.root, source2.prefix) : source2.root);
|
|
27497
27549
|
} catch {
|
|
27498
27550
|
continue;
|
|
27499
27551
|
}
|
|
27500
27552
|
for (const f of names2) {
|
|
27501
27553
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
27502
27554
|
seen.add(f);
|
|
27503
|
-
const relPath = source2.prefix ? (0,
|
|
27555
|
+
const relPath = source2.prefix ? (0, import_node_path32.join)(source2.prefix, f) : f;
|
|
27504
27556
|
const stat3 = statRegularInRoot(source2.root, relPath);
|
|
27505
27557
|
if (!stat3.ok) continue;
|
|
27506
27558
|
candidates2.push({ name: f, root: source2.root, relPath, mtime: stat3.mtimeMs, size: stat3.size });
|
|
@@ -27518,9 +27570,9 @@ function discoverPlans() {
|
|
|
27518
27570
|
function isRealDirectoryChain(root, parts2) {
|
|
27519
27571
|
let current = root;
|
|
27520
27572
|
for (const part of parts2) {
|
|
27521
|
-
current = (0,
|
|
27573
|
+
current = (0, import_node_path32.join)(current, part);
|
|
27522
27574
|
try {
|
|
27523
|
-
if (!(0,
|
|
27575
|
+
if (!(0, import_node_fs42.lstatSync)(current).isDirectory()) return false;
|
|
27524
27576
|
} catch {
|
|
27525
27577
|
return false;
|
|
27526
27578
|
}
|
|
@@ -27535,7 +27587,7 @@ function discoverGuardDocs(rangeFiles2) {
|
|
|
27535
27587
|
if (result.length >= MAX_SPEC_FILES) break;
|
|
27536
27588
|
if (!GUARD_DOC_EXT.test(path)) continue;
|
|
27537
27589
|
if (path.startsWith("/") || path.includes("..")) continue;
|
|
27538
|
-
if (!(0,
|
|
27590
|
+
if (!(0, import_node_fs42.existsSync)(path)) continue;
|
|
27539
27591
|
const opened = openRegularInRoot(process.cwd(), path);
|
|
27540
27592
|
if (!opened.ok) continue;
|
|
27541
27593
|
if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
|
|
@@ -27721,8 +27773,8 @@ async function mode(run4) {
|
|
|
27721
27773
|
}
|
|
27722
27774
|
|
|
27723
27775
|
// src/lib/fold.ts
|
|
27724
|
-
var
|
|
27725
|
-
var
|
|
27776
|
+
var import_node_fs43 = require("node:fs");
|
|
27777
|
+
var import_node_path33 = require("node:path");
|
|
27726
27778
|
var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
|
|
27727
27779
|
"user",
|
|
27728
27780
|
"assistant",
|
|
@@ -27859,7 +27911,7 @@ function candidateRoots(repoRoot2) {
|
|
|
27859
27911
|
const norm2 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
27860
27912
|
const out2 = [norm2];
|
|
27861
27913
|
try {
|
|
27862
|
-
const real =
|
|
27914
|
+
const real = import_node_fs43.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
27863
27915
|
if (real !== norm2) out2.push(real);
|
|
27864
27916
|
} catch {
|
|
27865
27917
|
}
|
|
@@ -27947,31 +27999,31 @@ function fold(transcriptPath, opts = {}) {
|
|
|
27947
27999
|
}
|
|
27948
28000
|
};
|
|
27949
28001
|
try {
|
|
27950
|
-
if (!(0,
|
|
27951
|
-
ingest((0,
|
|
28002
|
+
if (!(0, import_node_fs43.existsSync)(transcriptPath)) return result;
|
|
28003
|
+
ingest((0, import_node_fs43.readFileSync)(transcriptPath, "utf8"), "agent");
|
|
27952
28004
|
result.coverage.complete = true;
|
|
27953
28005
|
} catch {
|
|
27954
28006
|
return result;
|
|
27955
28007
|
}
|
|
27956
28008
|
try {
|
|
27957
|
-
const sidecarDir = (0,
|
|
27958
|
-
(0,
|
|
27959
|
-
(0,
|
|
28009
|
+
const sidecarDir = (0, import_node_path33.join)(
|
|
28010
|
+
(0, import_node_path33.dirname)(transcriptPath),
|
|
28011
|
+
(0, import_node_path33.basename)(transcriptPath).replace(/\.jsonl$/, ""),
|
|
27960
28012
|
"subagents"
|
|
27961
28013
|
);
|
|
27962
|
-
if ((0,
|
|
28014
|
+
if ((0, import_node_fs43.existsSync)(sidecarDir)) {
|
|
27963
28015
|
const maxFiles = opts.maxSidecars ?? 200;
|
|
27964
28016
|
const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
|
|
27965
28017
|
const found = [];
|
|
27966
28018
|
const walk2 = (d, depth) => {
|
|
27967
28019
|
if (depth > 4) return;
|
|
27968
|
-
for (const e of (0,
|
|
27969
|
-
const p = (0,
|
|
28020
|
+
for (const e of (0, import_node_fs43.readdirSync)(d, { withFileTypes: true })) {
|
|
28021
|
+
const p = (0, import_node_path33.join)(d, e.name);
|
|
27970
28022
|
if (e.isDirectory()) {
|
|
27971
28023
|
walk2(p, depth + 1);
|
|
27972
28024
|
} else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
|
|
27973
28025
|
try {
|
|
27974
|
-
const st = (0,
|
|
28026
|
+
const st = (0, import_node_fs43.statSync)(p);
|
|
27975
28027
|
found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
|
|
27976
28028
|
} catch {
|
|
27977
28029
|
result.coverage.malformed++;
|
|
@@ -27988,7 +28040,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
27988
28040
|
continue;
|
|
27989
28041
|
}
|
|
27990
28042
|
try {
|
|
27991
|
-
ingest((0,
|
|
28043
|
+
ingest((0, import_node_fs43.readFileSync)(f.path, "utf8"), "subagent");
|
|
27992
28044
|
bytes += f.size;
|
|
27993
28045
|
result.coverage.subagentFiles++;
|
|
27994
28046
|
} catch {
|
|
@@ -28023,7 +28075,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
28023
28075
|
}
|
|
28024
28076
|
function classifyUnobserved(path) {
|
|
28025
28077
|
try {
|
|
28026
|
-
const st = (0,
|
|
28078
|
+
const st = (0, import_node_fs43.statSync)(path);
|
|
28027
28079
|
if (!st.isFile()) return "unreadable";
|
|
28028
28080
|
} catch {
|
|
28029
28081
|
return "unreadable";
|
|
@@ -28338,20 +28390,20 @@ async function evidence(run4) {
|
|
|
28338
28390
|
}
|
|
28339
28391
|
|
|
28340
28392
|
// src/lib/cache-cleanup.ts
|
|
28341
|
-
var
|
|
28342
|
-
var
|
|
28393
|
+
var import_node_fs44 = require("node:fs");
|
|
28394
|
+
var import_node_path34 = require("node:path");
|
|
28343
28395
|
var CACHE_TTL_DAYS = 7;
|
|
28344
28396
|
function pruneStaleCache() {
|
|
28345
28397
|
try {
|
|
28346
28398
|
const dir = projectPath(CACHE_DIR);
|
|
28347
28399
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
28348
|
-
for (const entry of (0,
|
|
28400
|
+
for (const entry of (0, import_node_fs44.readdirSync)(dir)) {
|
|
28349
28401
|
if (!entry.startsWith("pending-")) continue;
|
|
28350
|
-
const path = (0,
|
|
28402
|
+
const path = (0, import_node_path34.join)(dir, entry);
|
|
28351
28403
|
try {
|
|
28352
|
-
const stat3 = (0,
|
|
28404
|
+
const stat3 = (0, import_node_fs44.statSync)(path);
|
|
28353
28405
|
if (stat3.mtimeMs < cutoff) {
|
|
28354
|
-
(0,
|
|
28406
|
+
(0, import_node_fs44.unlinkSync)(path);
|
|
28355
28407
|
logEvent("cache_entry_pruned", {
|
|
28356
28408
|
path: entry,
|
|
28357
28409
|
age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
|
|
@@ -28365,7 +28417,7 @@ function pruneStaleCache() {
|
|
|
28365
28417
|
}
|
|
28366
28418
|
|
|
28367
28419
|
// src/lib/context-files.ts
|
|
28368
|
-
var
|
|
28420
|
+
var import_node_fs45 = require("node:fs");
|
|
28369
28421
|
var import_node_os7 = require("node:os");
|
|
28370
28422
|
var MAX_CONTEXT_FILES = 10;
|
|
28371
28423
|
var MAX_CONTEXT_FILE_BYTES = 10240;
|
|
@@ -28423,7 +28475,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
|
|
|
28423
28475
|
continue;
|
|
28424
28476
|
}
|
|
28425
28477
|
try {
|
|
28426
|
-
const content = (0,
|
|
28478
|
+
const content = (0, import_node_fs45.readFileSync)(safePath, "utf8");
|
|
28427
28479
|
const bytes = Buffer.byteLength(content);
|
|
28428
28480
|
if (bytes > MAX_CONTEXT_FILE_BYTES) {
|
|
28429
28481
|
logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
|
|
@@ -28581,8 +28633,8 @@ function languageOf2(path) {
|
|
|
28581
28633
|
}
|
|
28582
28634
|
|
|
28583
28635
|
// src/lib/code/runtime.ts
|
|
28584
|
-
var
|
|
28585
|
-
var
|
|
28636
|
+
var import_node_fs46 = require("node:fs");
|
|
28637
|
+
var import_node_path35 = require("node:path");
|
|
28586
28638
|
var import_web_tree_sitter2 = __toESM2(require_web_tree_sitter2());
|
|
28587
28639
|
|
|
28588
28640
|
// src/lib/code/grammars.json
|
|
@@ -28642,18 +28694,18 @@ var grammars_default = {
|
|
|
28642
28694
|
var MAX_PARSE_BYTES = 512 * 1024;
|
|
28643
28695
|
function grammarCandidates(file, pkg, env = process.env) {
|
|
28644
28696
|
return [
|
|
28645
|
-
...env.VERITY_GRAMMAR_DIR ? [(0,
|
|
28646
|
-
(0,
|
|
28697
|
+
...env.VERITY_GRAMMAR_DIR ? [(0, import_node_path35.join)(env.VERITY_GRAMMAR_DIR, file)] : [],
|
|
28698
|
+
(0, import_node_path35.join)(__dirname, "..", "data", "grammars", file),
|
|
28647
28699
|
// bundled: cli/bin/ → cli/data/grammars/
|
|
28648
|
-
(0,
|
|
28700
|
+
(0, import_node_path35.join)(__dirname, "..", "..", "..", "data", "grammars", file),
|
|
28649
28701
|
// tsx: cli/src/lib/code/ → cli/data/grammars/
|
|
28650
|
-
(0,
|
|
28702
|
+
(0, import_node_path35.join)(__dirname, "..", "..", "..", "node_modules", pkg, file)
|
|
28651
28703
|
// tsx, before a build: the pinned devDependency
|
|
28652
28704
|
];
|
|
28653
28705
|
}
|
|
28654
28706
|
function locateGrammar(id, env = process.env) {
|
|
28655
28707
|
const g = grammars_default[id];
|
|
28656
|
-
return grammarCandidates(g.file, g.package, env).find((p) => (0,
|
|
28708
|
+
return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs46.existsSync)(p)) ?? null;
|
|
28657
28709
|
}
|
|
28658
28710
|
var loading = null;
|
|
28659
28711
|
function loadRuntime(env = process.env) {
|
|
@@ -30982,8 +31034,8 @@ async function repoContext(run4) {
|
|
|
30982
31034
|
|
|
30983
31035
|
// src/lib/seed-runner.ts
|
|
30984
31036
|
var import_promises15 = require("node:fs/promises");
|
|
30985
|
-
var
|
|
30986
|
-
var
|
|
31037
|
+
var import_node_fs47 = require("node:fs");
|
|
31038
|
+
var import_node_path36 = require("node:path");
|
|
30987
31039
|
var import_yaml4 = __toESM2(require_dist());
|
|
30988
31040
|
|
|
30989
31041
|
// src/lib/seed.ts
|
|
@@ -31206,8 +31258,8 @@ function normalizeTitle(title) {
|
|
|
31206
31258
|
async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
|
|
31207
31259
|
const titles = /* @__PURE__ */ new Set();
|
|
31208
31260
|
for (const dir of NODE_DIRS) {
|
|
31209
|
-
const full = (0,
|
|
31210
|
-
if (!(0,
|
|
31261
|
+
const full = (0, import_node_path36.join)(memoryDir3, dir);
|
|
31262
|
+
if (!(0, import_node_fs47.existsSync)(full)) continue;
|
|
31211
31263
|
let files;
|
|
31212
31264
|
try {
|
|
31213
31265
|
files = await (0, import_promises15.readdir)(full);
|
|
@@ -31218,7 +31270,7 @@ async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
|
|
|
31218
31270
|
if (!file.endsWith(".md")) continue;
|
|
31219
31271
|
let content;
|
|
31220
31272
|
try {
|
|
31221
|
-
content = await (0, import_promises15.readFile)((0,
|
|
31273
|
+
content = await (0, import_promises15.readFile)((0, import_node_path36.join)(full, file), "utf-8");
|
|
31222
31274
|
} catch {
|
|
31223
31275
|
continue;
|
|
31224
31276
|
}
|
|
@@ -31289,7 +31341,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
|
|
|
31289
31341
|
return fm;
|
|
31290
31342
|
}
|
|
31291
31343
|
async function runSeed(opts) {
|
|
31292
|
-
if (!(0,
|
|
31344
|
+
if (!(0, import_node_fs47.existsSync)(STANDARD_FILE)) {
|
|
31293
31345
|
return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
|
|
31294
31346
|
}
|
|
31295
31347
|
let standardDoc;
|
|
@@ -31301,7 +31353,7 @@ async function runSeed(opts) {
|
|
|
31301
31353
|
}
|
|
31302
31354
|
const knowledgeSpec = standardDoc.knowledge_spec ?? {};
|
|
31303
31355
|
let readmeContent;
|
|
31304
|
-
if ((0,
|
|
31356
|
+
if ((0, import_node_fs47.existsSync)("README.md")) {
|
|
31305
31357
|
try {
|
|
31306
31358
|
readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
|
|
31307
31359
|
} catch {
|
|
@@ -31309,7 +31361,7 @@ async function runSeed(opts) {
|
|
|
31309
31361
|
}
|
|
31310
31362
|
let claudeMdContent;
|
|
31311
31363
|
for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
|
|
31312
|
-
if ((0,
|
|
31364
|
+
if ((0, import_node_fs47.existsSync)(p)) {
|
|
31313
31365
|
try {
|
|
31314
31366
|
claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
|
|
31315
31367
|
break;
|
|
@@ -31389,13 +31441,13 @@ async function runSeed(opts) {
|
|
|
31389
31441
|
continue;
|
|
31390
31442
|
}
|
|
31391
31443
|
const deduplicated = res.data.deduplicated === true;
|
|
31392
|
-
if (deduplicated && (0,
|
|
31444
|
+
if (deduplicated && (0, import_node_fs47.existsSync)(targetPath)) {
|
|
31393
31445
|
existing++;
|
|
31394
31446
|
continue;
|
|
31395
31447
|
}
|
|
31396
31448
|
const content = typeof res.data.content === "string" && res.data.content.length > 0 ? res.data.content : renderNodeMarkdown(c, nodeId, createdAt);
|
|
31397
31449
|
try {
|
|
31398
|
-
await (0, import_promises15.mkdir)((0,
|
|
31450
|
+
await (0, import_promises15.mkdir)((0, import_node_path36.dirname)(targetPath), { recursive: true });
|
|
31399
31451
|
await (0, import_promises15.writeFile)(targetPath, content);
|
|
31400
31452
|
if (deduplicated) existing++;
|
|
31401
31453
|
else {
|
|
@@ -31411,8 +31463,8 @@ async function runSeed(opts) {
|
|
|
31411
31463
|
}
|
|
31412
31464
|
|
|
31413
31465
|
// src/commands/analyze/phases/08-memory-manifest.ts
|
|
31414
|
-
var
|
|
31415
|
-
var
|
|
31466
|
+
var import_node_fs48 = require("node:fs");
|
|
31467
|
+
var import_node_path37 = require("node:path");
|
|
31416
31468
|
async function memoryManifest(run4) {
|
|
31417
31469
|
const { globals } = run4;
|
|
31418
31470
|
const { serviceUrl, token } = run4;
|
|
@@ -31422,9 +31474,9 @@ async function memoryManifest(run4) {
|
|
|
31422
31474
|
let autoSeedNotice = null;
|
|
31423
31475
|
try {
|
|
31424
31476
|
await ensureMemoryDir();
|
|
31425
|
-
const seedMarker = (0,
|
|
31426
|
-
const hasStandard = (0,
|
|
31427
|
-
const alreadyTried = (0,
|
|
31477
|
+
const seedMarker = (0, import_node_path37.join)(VERITY_DIR, ".seeded");
|
|
31478
|
+
const hasStandard = (0, import_node_fs48.existsSync)(STANDARD_FILE);
|
|
31479
|
+
const alreadyTried = (0, import_node_fs48.existsSync)(seedMarker);
|
|
31428
31480
|
if (hasStandard && !alreadyTried) {
|
|
31429
31481
|
const preManifest = await buildManifest();
|
|
31430
31482
|
if (preManifest.nodes.length === 0) {
|
|
@@ -31437,7 +31489,7 @@ async function memoryManifest(run4) {
|
|
|
31437
31489
|
dryRun: false
|
|
31438
31490
|
});
|
|
31439
31491
|
if (seedResult.created > 0 || seedResult.existing > 0) {
|
|
31440
|
-
(0,
|
|
31492
|
+
(0, import_node_fs48.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
|
|
31441
31493
|
`);
|
|
31442
31494
|
if (seedResult.created > 0) {
|
|
31443
31495
|
autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
|
|
@@ -31448,7 +31500,7 @@ async function memoryManifest(run4) {
|
|
|
31448
31500
|
failed: seedResult.failed
|
|
31449
31501
|
});
|
|
31450
31502
|
} else if (seedResult.skipped === "already_seeded") {
|
|
31451
|
-
(0,
|
|
31503
|
+
(0, import_node_fs48.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
|
|
31452
31504
|
`);
|
|
31453
31505
|
} else {
|
|
31454
31506
|
logEvent("auto_seed_noop", {
|
|
@@ -31543,7 +31595,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
|
|
|
31543
31595
|
}
|
|
31544
31596
|
|
|
31545
31597
|
// src/commands/analyze/phases/10-working-memory.ts
|
|
31546
|
-
var
|
|
31598
|
+
var import_node_path38 = require("node:path");
|
|
31547
31599
|
async function workingMemory(run4) {
|
|
31548
31600
|
const { opts } = run4;
|
|
31549
31601
|
const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run4;
|
|
@@ -31555,7 +31607,7 @@ async function workingMemory(run4) {
|
|
|
31555
31607
|
const priorState = foldForMarks(memorySession.d);
|
|
31556
31608
|
incrementReport = computeIncrement(
|
|
31557
31609
|
allForReview,
|
|
31558
|
-
(p) => fileHash((0,
|
|
31610
|
+
(p) => fileHash((0, import_node_path38.join)(repoRoot(), p)),
|
|
31559
31611
|
priorState.authored_all.map((a) => ({
|
|
31560
31612
|
path: a.path,
|
|
31561
31613
|
hash_at_last_verdict: a.hash_at_last_verdict
|
|
@@ -31637,7 +31689,7 @@ async function workingMemory(run4) {
|
|
|
31637
31689
|
}
|
|
31638
31690
|
|
|
31639
31691
|
// src/lib/note-budget.ts
|
|
31640
|
-
var
|
|
31692
|
+
var import_node_fs49 = require("node:fs");
|
|
31641
31693
|
var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
|
|
31642
31694
|
var EPISODE_STALE_SECONDS = 30 * 60;
|
|
31643
31695
|
var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
|
|
@@ -31659,9 +31711,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
|
|
|
31659
31711
|
}
|
|
31660
31712
|
function readAdvisoryEpisode(sessionId) {
|
|
31661
31713
|
const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
|
|
31662
|
-
if (!(0,
|
|
31714
|
+
if (!(0, import_node_fs49.existsSync)(file)) return null;
|
|
31663
31715
|
try {
|
|
31664
|
-
const o = JSON.parse((0,
|
|
31716
|
+
const o = JSON.parse((0, import_node_fs49.readFileSync)(file, "utf-8")) ?? {};
|
|
31665
31717
|
const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
|
|
31666
31718
|
if (isNaN(delivered)) return null;
|
|
31667
31719
|
return {
|
|
@@ -31675,8 +31727,8 @@ function readAdvisoryEpisode(sessionId) {
|
|
|
31675
31727
|
}
|
|
31676
31728
|
function writeAdvisoryEpisode(episode, sessionId) {
|
|
31677
31729
|
try {
|
|
31678
|
-
(0,
|
|
31679
|
-
(0,
|
|
31730
|
+
(0, import_node_fs49.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
31731
|
+
(0, import_node_fs49.writeFileSync)(
|
|
31680
31732
|
scopedFile(ADVISORY_EPISODE_FILE, sessionId),
|
|
31681
31733
|
JSON.stringify({ v: 1, ...episode })
|
|
31682
31734
|
);
|
|
@@ -32008,14 +32060,14 @@ async function buildRequest(run4) {
|
|
|
32008
32060
|
}
|
|
32009
32061
|
|
|
32010
32062
|
// src/lib/offline.ts
|
|
32011
|
-
var
|
|
32063
|
+
var import_node_fs50 = require("node:fs");
|
|
32012
32064
|
var import_node_crypto13 = require("node:crypto");
|
|
32013
32065
|
function cacheRequest(body2) {
|
|
32014
32066
|
try {
|
|
32015
|
-
(0,
|
|
32067
|
+
(0, import_node_fs50.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
32016
32068
|
const suffix = (0, import_node_crypto13.randomBytes)(4).toString("hex");
|
|
32017
32069
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
32018
|
-
(0,
|
|
32070
|
+
(0, import_node_fs50.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
|
|
32019
32071
|
} catch {
|
|
32020
32072
|
}
|
|
32021
32073
|
}
|
|
@@ -32134,8 +32186,8 @@ async function transmit(run4) {
|
|
|
32134
32186
|
}
|
|
32135
32187
|
|
|
32136
32188
|
// src/commands/analyze/phases/13-reconcile.ts
|
|
32137
|
-
var
|
|
32138
|
-
var
|
|
32189
|
+
var import_node_fs51 = require("node:fs");
|
|
32190
|
+
var import_node_path39 = require("node:path");
|
|
32139
32191
|
async function reconcile(run4) {
|
|
32140
32192
|
const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory: memory2, memorySession, response, reviewable, securityFiles, turnId } = run4;
|
|
32141
32193
|
const sentPaths = codeDelta.files.map((f) => f.path);
|
|
@@ -32164,7 +32216,7 @@ async function reconcile(run4) {
|
|
|
32164
32216
|
const st = foldDossier(memorySession.d);
|
|
32165
32217
|
openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line2) => {
|
|
32166
32218
|
try {
|
|
32167
|
-
const src = (0,
|
|
32219
|
+
const src = (0, import_node_fs51.readFileSync)((0, import_node_path39.join)(repoRoot(), file), "utf8").split("\n");
|
|
32168
32220
|
const at = src[line2 - 1];
|
|
32169
32221
|
return at === void 0 ? null : lineSha(at);
|
|
32170
32222
|
} catch {
|
|
@@ -32986,7 +33038,7 @@ function registerAnalyzeCommand(program2) {
|
|
|
32986
33038
|
var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
|
|
32987
33039
|
async function runAnalyze(opts, globals) {
|
|
32988
33040
|
if (!verityConfigured()) {
|
|
32989
|
-
(0,
|
|
33041
|
+
(0, import_node_fs52.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
|
|
32990
33042
|
process.exit(0);
|
|
32991
33043
|
}
|
|
32992
33044
|
const run4 = createRun(opts, globals);
|
|
@@ -33007,11 +33059,11 @@ async function runAnalyze(opts, globals) {
|
|
|
33007
33059
|
}
|
|
33008
33060
|
|
|
33009
33061
|
// src/commands/baseline.ts
|
|
33010
|
-
var
|
|
33062
|
+
var import_node_fs54 = require("node:fs");
|
|
33011
33063
|
|
|
33012
33064
|
// src/lib/project-skills.ts
|
|
33013
|
-
var
|
|
33014
|
-
var
|
|
33065
|
+
var import_node_fs53 = require("node:fs");
|
|
33066
|
+
var import_node_path40 = require("node:path");
|
|
33015
33067
|
var PROJECT_SKILL_NAMES = [
|
|
33016
33068
|
"verity-setup",
|
|
33017
33069
|
"verity-analyze",
|
|
@@ -33037,14 +33089,14 @@ var LEGACY_SKILL_NAMES = [
|
|
|
33037
33089
|
var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
|
|
33038
33090
|
function staleProjectSkills() {
|
|
33039
33091
|
const root = projectPath(".claude/skills");
|
|
33040
|
-
if (!(0,
|
|
33041
|
-
return ALL.filter((name2) => (0,
|
|
33092
|
+
if (!(0, import_node_fs53.existsSync)(root)) return [];
|
|
33093
|
+
return ALL.filter((name2) => (0, import_node_fs53.existsSync)((0, import_node_path40.join)(root, name2)));
|
|
33042
33094
|
}
|
|
33043
33095
|
function removeProjectSkills() {
|
|
33044
33096
|
const root = projectPath(".claude/skills");
|
|
33045
33097
|
const removed = [];
|
|
33046
33098
|
for (const name2 of staleProjectSkills()) {
|
|
33047
|
-
(0,
|
|
33099
|
+
(0, import_node_fs53.rmSync)((0, import_node_path40.join)(root, name2), { recursive: true, force: true });
|
|
33048
33100
|
removed.push(name2);
|
|
33049
33101
|
}
|
|
33050
33102
|
return removed;
|
|
@@ -33109,13 +33161,13 @@ function registerBaselineCommands(program2) {
|
|
|
33109
33161
|
let memoryMsg = null;
|
|
33110
33162
|
let memoryAgentLine = null;
|
|
33111
33163
|
const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
|
|
33112
|
-
if (realStart && !(0,
|
|
33164
|
+
if (realStart && !(0, import_node_fs54.existsSync)(memoryNotice)) {
|
|
33113
33165
|
const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
|
|
33114
33166
|
if (trackedGraph > 0) {
|
|
33115
33167
|
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.`;
|
|
33116
33168
|
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.`;
|
|
33117
33169
|
try {
|
|
33118
|
-
(0,
|
|
33170
|
+
(0, import_node_fs54.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
|
|
33119
33171
|
} catch {
|
|
33120
33172
|
}
|
|
33121
33173
|
}
|
|
@@ -33216,7 +33268,7 @@ function hookSource(value) {
|
|
|
33216
33268
|
}
|
|
33217
33269
|
|
|
33218
33270
|
// src/commands/review.ts
|
|
33219
|
-
var
|
|
33271
|
+
var import_node_fs55 = require("node:fs");
|
|
33220
33272
|
function registerReviewCommand(program2) {
|
|
33221
33273
|
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) => {
|
|
33222
33274
|
const globals = program2.opts();
|
|
@@ -33233,7 +33285,7 @@ async function runReview(opts, globals) {
|
|
|
33233
33285
|
const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
|
|
33234
33286
|
const analyzable = filterAnalyzable(allFiles);
|
|
33235
33287
|
const securityFiles = filterSecurity(allFiles);
|
|
33236
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
33288
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs55.existsSync)(f) || resolveFile(f) !== null);
|
|
33237
33289
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
33238
33290
|
const codeDelta = collectCodeDelta(allFiles);
|
|
33239
33291
|
const tokenResult = await resolveToken(globals.token);
|
|
@@ -33299,8 +33351,8 @@ async function runReview(opts, globals) {
|
|
|
33299
33351
|
}
|
|
33300
33352
|
|
|
33301
33353
|
// src/commands/guard.ts
|
|
33302
|
-
var
|
|
33303
|
-
var
|
|
33354
|
+
var import_node_fs59 = require("node:fs");
|
|
33355
|
+
var import_node_path45 = require("node:path");
|
|
33304
33356
|
|
|
33305
33357
|
// src/lib/terminal-text.ts
|
|
33306
33358
|
var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
|
|
@@ -33408,7 +33460,7 @@ async function runAgentReview(options) {
|
|
|
33408
33460
|
}
|
|
33409
33461
|
|
|
33410
33462
|
// src/lib/prove/auto.ts
|
|
33411
|
-
var
|
|
33463
|
+
var import_node_path44 = require("node:path");
|
|
33412
33464
|
var import_node_crypto18 = require("node:crypto");
|
|
33413
33465
|
|
|
33414
33466
|
// src/lib/prove/signals.ts
|
|
@@ -33817,6 +33869,11 @@ async function rankViaServer(candidates2, ctx, auth2) {
|
|
|
33817
33869
|
cmd: "prove-rank"
|
|
33818
33870
|
});
|
|
33819
33871
|
if (!res.ok) return { ok: false, ranker: "luna", error: res.error, ranked: fallback };
|
|
33872
|
+
const off = res.data;
|
|
33873
|
+
if (off?.enabled === false) {
|
|
33874
|
+
const why = typeof off.reason === "string" ? off.reason.slice(0, 40) : "disabled";
|
|
33875
|
+
return { ok: false, ranker: "luna", error: `formal is off for this project (${why})`, ranked: fallback, disabled: why };
|
|
33876
|
+
}
|
|
33820
33877
|
const items = Array.isArray(res.data?.items) ? res.data.items : [];
|
|
33821
33878
|
return { ok: true, ranker: "luna", ranked: applyAnnotations(candidates2, items), costUsd: typeof res.data?.cost_usd === "number" ? res.data.cost_usd : null };
|
|
33822
33879
|
}
|
|
@@ -34541,6 +34598,8 @@ async function generateModel(target, opts) {
|
|
|
34541
34598
|
});
|
|
34542
34599
|
if (!res.ok) return { ok: false, error: res.error };
|
|
34543
34600
|
const d = res.data ?? {};
|
|
34601
|
+
const off = d;
|
|
34602
|
+
if (off.enabled === false) return { ok: false, error: `formal is off for this project (${typeof off.reason === "string" ? off.reason.slice(0, 40) : "disabled"})` };
|
|
34544
34603
|
if (d.error && typeof d.error === "object") return { ok: false, error: `${d.error.code ?? "SERVICE_ERROR"}: ${d.error.message ?? "the service failed"}` };
|
|
34545
34604
|
const usage2 = d.usage && typeof d.usage === "object" ? { inputTokens: Number(d.usage.inputTokens ?? 0), outputTokens: Number(d.usage.outputTokens ?? 0) } : null;
|
|
34546
34605
|
return acceptAnswer(d, usage2, typeof d.cost_usd === "number" ? d.cost_usd : null);
|
|
@@ -34720,8 +34779,7 @@ Rules:
|
|
|
34720
34779
|
5. Write the harness as ONE file and run it in the SAME shell call that writes it (a heredoc followed by the run). TypeScript: node --experimental-strip-types harness.ts (detect runtimes only if that fails: node --version, python3 --version); if strip-types is unavailable, remove type annotations ONLY on lines that are not part of the function under test's logic, and say so. Python: python3 harness.py.
|
|
34721
34780
|
6. Nothing you run can reach the network. Do not try.
|
|
34722
34781
|
7. Keep it under about eight shell calls. Output tokens are time.
|
|
34723
|
-
8. Answer with the JSON object only: verdict (reproduced | diverged | unreplayable), reason (2-4 sentences: what you ran, what the real code did, and how that compares to the trace's final state), harness_files (every file you wrote: path and its line count \u2014 do NOT paste contents, your shell calls already carry them), executed_output (the last relevant stdout, at most 2000 characters)
|
|
34724
|
-
9. impact \u2014 AFTER the verdict, and never a reason to change it: what the violation you ran costs a user of this code, the most serious one the run showed. money: a balance, charge, refund, price or stock is wrong. access: someone gets access they should not have, or an auth check is bypassed. data: a user's records are lost, corrupted or wrongly duplicated. external: an effect outside the system happens twice or never (a charge, an email, a shipment, a webhook). count: a counter, metric or statistic is off. cache: a cached or derived value is stale until it refreshes. internal: the program's own bookkeeping is off, with no effect a user would see. none: the verdict is not reproduced.
|
|
34782
|
+
8. Answer with the JSON object only: verdict (reproduced | diverged | unreplayable), reason (2-4 sentences: what you ran, what the real code did, and how that compares to the trace's final state), harness_files (every file you wrote: path and its line count \u2014 do NOT paste contents, your shell calls already carry them), executed_output (the last relevant stdout, at most 2000 characters).
|
|
34725
34783
|
|
|
34726
34784
|
"reproduced" means the real code, driven by the trace, reached the property violation the model describes. "diverged" means it did not \u2014 the model is wrong about the code, which is a useful answer. "unreplayable" means you could not run the real function faithfully; say why.`;
|
|
34727
34785
|
var REPLAY_SCHEMA = {
|
|
@@ -34739,10 +34797,9 @@ var REPLAY_SCHEMA = {
|
|
|
34739
34797
|
required: ["path", "lines"]
|
|
34740
34798
|
}
|
|
34741
34799
|
},
|
|
34742
|
-
executed_output: { type: "string" }
|
|
34743
|
-
impact: { type: "string", enum: ["money", "access", "data", "external", "count", "cache", "internal", "none"] }
|
|
34800
|
+
executed_output: { type: "string" }
|
|
34744
34801
|
},
|
|
34745
|
-
required: ["verdict", "reason", "harness_files", "executed_output"
|
|
34802
|
+
required: ["verdict", "reason", "harness_files", "executed_output"]
|
|
34746
34803
|
};
|
|
34747
34804
|
function renderBriefInput(brief) {
|
|
34748
34805
|
const p = brief.property;
|
|
@@ -34769,8 +34826,6 @@ function renderBriefInput(brief) {
|
|
|
34769
34826
|
}
|
|
34770
34827
|
return parts2.join("\n");
|
|
34771
34828
|
}
|
|
34772
|
-
var IMPACTS = ["money", "access", "data", "external", "count", "cache", "internal", "none"];
|
|
34773
|
-
var isImpact = (v) => typeof v === "string" && IMPACTS.includes(v);
|
|
34774
34829
|
function stringsIn(value, out2 = [], depth = 0) {
|
|
34775
34830
|
if (depth > 8) return out2;
|
|
34776
34831
|
if (typeof value === "string") out2.push(value);
|
|
@@ -34812,8 +34867,7 @@ function parseReplayOutput(output) {
|
|
|
34812
34867
|
verdict,
|
|
34813
34868
|
reason: typeof o.reason === "string" ? o.reason.slice(0, 2e3) : "",
|
|
34814
34869
|
harness_files: Array.isArray(o.harness_files) ? o.harness_files.filter((f) => typeof f.path === "string").map((f) => ({ path: String(f.path).slice(0, 200), lines: Number.isInteger(f.lines) ? f.lines : 0 })) : [],
|
|
34815
|
-
executed_output: typeof o.executed_output === "string" ? o.executed_output.slice(0, 2e3) : ""
|
|
34816
|
-
impact: isImpact(o.impact) ? o.impact : "none"
|
|
34870
|
+
executed_output: typeof o.executed_output === "string" ? o.executed_output.slice(0, 2e3) : ""
|
|
34817
34871
|
};
|
|
34818
34872
|
}
|
|
34819
34873
|
} catch {
|
|
@@ -34821,10 +34875,10 @@ function parseReplayOutput(output) {
|
|
|
34821
34875
|
}
|
|
34822
34876
|
return { claim, shellCalls, executedCalls, shellTexts, outputTexts };
|
|
34823
34877
|
}
|
|
34824
|
-
var RESULT_LINE = /REPLAY_RESULT=(reproduced|diverged)\b
|
|
34878
|
+
var RESULT_LINE = /REPLAY_RESULT=(reproduced|diverged)\b/g;
|
|
34825
34879
|
function printedResult(outputTexts) {
|
|
34826
34880
|
let last = null;
|
|
34827
|
-
for (const t of outputTexts) for (const m of t.matchAll(
|
|
34881
|
+
for (const t of outputTexts) for (const m of t.matchAll(RESULT_LINE)) last = m[1];
|
|
34828
34882
|
return last;
|
|
34829
34883
|
}
|
|
34830
34884
|
var RESULT_MISSING = "the harness never printed REPLAY_RESULT=reproduced on its own stdout \u2014 the verdict was the model's word, not the run's";
|
|
@@ -35014,7 +35068,6 @@ async function runReplayInContainer(brief, opts) {
|
|
|
35014
35068
|
...judged,
|
|
35015
35069
|
executedCalls,
|
|
35016
35070
|
shellCalls,
|
|
35017
|
-
...judged.verdict === "reproduced" && parsed.claim ? { impact: parsed.claim.impact } : {},
|
|
35018
35071
|
executedOutput: parsed.claim?.executed_output ?? "",
|
|
35019
35072
|
harnessFiles: parsed.claim?.harness_files ?? [],
|
|
35020
35073
|
usage,
|
|
@@ -35061,6 +35114,11 @@ async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
|
|
|
35061
35114
|
return { claimed: null, verdict: "unverified", reason: "", downgrade: res.error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: Date.now() - started, containerId: null, error: res.error };
|
|
35062
35115
|
}
|
|
35063
35116
|
const d = res.data ?? {};
|
|
35117
|
+
if (d.enabled === false) {
|
|
35118
|
+
const why = d.reason;
|
|
35119
|
+
const msg = `formal is off for this project (${typeof why === "string" ? why.slice(0, 40) : "disabled"})`;
|
|
35120
|
+
return { claimed: null, verdict: "unverified", reason: "", downgrade: msg, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: Date.now() - started, containerId: null, error: msg };
|
|
35121
|
+
}
|
|
35064
35122
|
if (d.error && typeof d.error === "object") {
|
|
35065
35123
|
const e = d.error;
|
|
35066
35124
|
const msg = `${e.code ?? "SERVICE_ERROR"}: ${e.message ?? "the service failed"}`;
|
|
@@ -35073,7 +35131,6 @@ async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
|
|
|
35073
35131
|
verdict: verdict === "reproduced" || verdict === "diverged" || verdict === "unreplayable" ? verdict : "unverified",
|
|
35074
35132
|
reason: typeof d.reason === "string" ? d.reason : "",
|
|
35075
35133
|
downgrade: typeof d.downgrade === "string" ? d.downgrade : null,
|
|
35076
|
-
...isImpact(d.impact) ? { impact: d.impact } : {},
|
|
35077
35134
|
executedCalls: Number(d.executed_calls ?? 0),
|
|
35078
35135
|
shellCalls: Number(d.shell_calls ?? 0),
|
|
35079
35136
|
verbatim: { covered: Number(v.covered ?? 0), total: Number(v.total ?? 0), ratio: Number(v.ratio ?? 0), basis: v.basis === "symbol" || v.basis === "file" ? v.basis : "none" },
|
|
@@ -35130,18 +35187,18 @@ function renderReplay(model, property, r) {
|
|
|
35130
35187
|
// src/lib/prove/runner.ts
|
|
35131
35188
|
var import_node_child_process15 = require("node:child_process");
|
|
35132
35189
|
var import_node_os8 = require("node:os");
|
|
35133
|
-
var
|
|
35190
|
+
var import_node_fs58 = require("node:fs");
|
|
35134
35191
|
var import_node_os9 = require("node:os");
|
|
35135
|
-
var
|
|
35192
|
+
var import_node_path43 = require("node:path");
|
|
35136
35193
|
|
|
35137
35194
|
// src/lib/prove/scaffold.ts
|
|
35138
|
-
var
|
|
35139
|
-
var
|
|
35195
|
+
var import_node_fs57 = require("node:fs");
|
|
35196
|
+
var import_node_path42 = require("node:path");
|
|
35140
35197
|
|
|
35141
35198
|
// src/lib/prove/safe-write.ts
|
|
35142
|
-
var
|
|
35199
|
+
var import_node_fs56 = require("node:fs");
|
|
35143
35200
|
var import_node_crypto14 = require("node:crypto");
|
|
35144
|
-
var
|
|
35201
|
+
var import_node_path41 = require("node:path");
|
|
35145
35202
|
var SafeWriteError = class extends Error {
|
|
35146
35203
|
constructor(reason, path) {
|
|
35147
35204
|
super(`refusing to write ${path}: ${reason}`);
|
|
@@ -35150,10 +35207,10 @@ var SafeWriteError = class extends Error {
|
|
|
35150
35207
|
this.name = "SafeWriteError";
|
|
35151
35208
|
}
|
|
35152
35209
|
};
|
|
35153
|
-
var FLAGS3 =
|
|
35210
|
+
var FLAGS3 = import_node_fs56.constants;
|
|
35154
35211
|
var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
|
|
35155
35212
|
function assertPlainRelative(rel) {
|
|
35156
|
-
if (!rel || (0,
|
|
35213
|
+
if (!rel || (0, import_node_path41.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
|
|
35157
35214
|
for (const part of rel.split(/[\\/]/)) {
|
|
35158
35215
|
if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
|
|
35159
35216
|
}
|
|
@@ -35162,34 +35219,34 @@ function ensureDirsNoFollow(root, rel) {
|
|
|
35162
35219
|
const parts2 = rel.split(/[\\/]/);
|
|
35163
35220
|
let cur = root;
|
|
35164
35221
|
for (const part of parts2.slice(0, -1)) {
|
|
35165
|
-
cur = (0,
|
|
35222
|
+
cur = (0, import_node_path41.join)(cur, part);
|
|
35166
35223
|
let st;
|
|
35167
35224
|
try {
|
|
35168
|
-
st = (0,
|
|
35225
|
+
st = (0, import_node_fs56.lstatSync)(cur);
|
|
35169
35226
|
} catch {
|
|
35170
|
-
(0,
|
|
35227
|
+
(0, import_node_fs56.mkdirSync)(cur);
|
|
35171
35228
|
continue;
|
|
35172
35229
|
}
|
|
35173
35230
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
|
|
35174
35231
|
if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
|
|
35175
35232
|
}
|
|
35176
|
-
return (0,
|
|
35233
|
+
return (0, import_node_path41.join)(root, rel);
|
|
35177
35234
|
}
|
|
35178
35235
|
function insideRoot(realRoot, realPath) {
|
|
35179
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
35236
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path41.sep) ? realRoot : realRoot + import_node_path41.sep);
|
|
35180
35237
|
}
|
|
35181
35238
|
function removeQuietly(path) {
|
|
35182
35239
|
try {
|
|
35183
|
-
(0,
|
|
35240
|
+
(0, import_node_fs56.unlinkSync)(path);
|
|
35184
35241
|
} catch {
|
|
35185
35242
|
}
|
|
35186
35243
|
}
|
|
35187
35244
|
function writeFileInRootNoFollow(root, rel, content) {
|
|
35188
35245
|
assertPlainRelative(rel);
|
|
35189
35246
|
const dest = ensureDirsNoFollow(root, rel);
|
|
35190
|
-
const dir = (0,
|
|
35247
|
+
const dir = (0, import_node_path41.dirname)(dest);
|
|
35191
35248
|
try {
|
|
35192
|
-
const st = (0,
|
|
35249
|
+
const st = (0, import_node_fs56.lstatSync)(dest);
|
|
35193
35250
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
|
|
35194
35251
|
if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
|
|
35195
35252
|
} catch (err2) {
|
|
@@ -35197,41 +35254,41 @@ function writeFileInRootNoFollow(root, rel, content) {
|
|
|
35197
35254
|
}
|
|
35198
35255
|
let realRoot;
|
|
35199
35256
|
try {
|
|
35200
|
-
realRoot = (0,
|
|
35257
|
+
realRoot = (0, import_node_fs56.realpathSync)(root);
|
|
35201
35258
|
} catch {
|
|
35202
35259
|
throw new SafeWriteError("unwritable", root);
|
|
35203
35260
|
}
|
|
35204
|
-
const tmp = (0,
|
|
35261
|
+
const tmp = (0, import_node_path41.join)(dir, `.${(0, import_node_path41.basename)(dest)}.${(0, import_node_crypto14.randomBytes)(6).toString("hex")}.tmp`);
|
|
35205
35262
|
let fd;
|
|
35206
35263
|
try {
|
|
35207
|
-
fd = (0,
|
|
35264
|
+
fd = (0, import_node_fs56.openSync)(tmp, import_node_fs56.constants.O_WRONLY | import_node_fs56.constants.O_CREAT | import_node_fs56.constants.O_EXCL | NOFOLLOW2, 420);
|
|
35208
35265
|
} catch {
|
|
35209
35266
|
throw new SafeWriteError("unwritable", tmp);
|
|
35210
35267
|
}
|
|
35211
35268
|
try {
|
|
35212
|
-
const opened = (0,
|
|
35269
|
+
const opened = (0, import_node_fs56.fstatSync)(fd, { bigint: true });
|
|
35213
35270
|
let realTmp;
|
|
35214
35271
|
try {
|
|
35215
|
-
realTmp = (0,
|
|
35272
|
+
realTmp = (0, import_node_fs56.realpathSync)(tmp);
|
|
35216
35273
|
} catch {
|
|
35217
35274
|
throw new SafeWriteError("escaped", tmp);
|
|
35218
35275
|
}
|
|
35219
|
-
const there = (0,
|
|
35276
|
+
const there = (0, import_node_fs56.lstatSync)(realTmp, { bigint: true });
|
|
35220
35277
|
if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
|
|
35221
35278
|
throw new SafeWriteError("escaped", tmp);
|
|
35222
35279
|
}
|
|
35223
35280
|
const buf = Buffer.from(content, "utf-8");
|
|
35224
35281
|
let off = 0;
|
|
35225
|
-
while (off < buf.length) off += (0,
|
|
35282
|
+
while (off < buf.length) off += (0, import_node_fs56.writeSync)(fd, buf, off, buf.length - off);
|
|
35226
35283
|
} catch (err2) {
|
|
35227
|
-
(0,
|
|
35284
|
+
(0, import_node_fs56.closeSync)(fd);
|
|
35228
35285
|
removeQuietly(tmp);
|
|
35229
35286
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
|
|
35230
35287
|
}
|
|
35231
|
-
(0,
|
|
35288
|
+
(0, import_node_fs56.closeSync)(fd);
|
|
35232
35289
|
try {
|
|
35233
|
-
if (!insideRoot(realRoot, (0,
|
|
35234
|
-
(0,
|
|
35290
|
+
if (!insideRoot(realRoot, (0, import_node_fs56.realpathSync)(dir)) || (0, import_node_fs56.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
|
|
35291
|
+
(0, import_node_fs56.renameSync)(tmp, dest);
|
|
35235
35292
|
} catch (err2) {
|
|
35236
35293
|
removeQuietly(tmp);
|
|
35237
35294
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
|
|
@@ -35245,9 +35302,9 @@ function pathHasNoLink(root, rel) {
|
|
|
35245
35302
|
}
|
|
35246
35303
|
let cur = root;
|
|
35247
35304
|
for (const part of rel.split(/[\\/]/)) {
|
|
35248
|
-
cur = cur +
|
|
35305
|
+
cur = cur + import_node_path41.sep + part;
|
|
35249
35306
|
try {
|
|
35250
|
-
if ((0,
|
|
35307
|
+
if ((0, import_node_fs56.lstatSync)(cur).isSymbolicLink()) return false;
|
|
35251
35308
|
} catch {
|
|
35252
35309
|
return true;
|
|
35253
35310
|
}
|
|
@@ -35557,20 +35614,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
|
|
|
35557
35614
|
never committed; what reaches the team is the bug report and the fix.
|
|
35558
35615
|
`;
|
|
35559
35616
|
function scaffoldProofs(root) {
|
|
35560
|
-
const proofsDir = (0,
|
|
35617
|
+
const proofsDir = (0, import_node_path42.join)(root, PROOFS_DIR);
|
|
35561
35618
|
const written = [];
|
|
35562
35619
|
const kept = [];
|
|
35563
35620
|
for (const stray of ["lakefile.lean"]) {
|
|
35564
35621
|
const rel = `${PROOFS_DIR}/${stray}`;
|
|
35565
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
35622
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
|
|
35566
35623
|
try {
|
|
35567
|
-
(0,
|
|
35624
|
+
(0, import_node_fs57.rmSync)((0, import_node_path42.join)(root, rel), { force: true });
|
|
35568
35625
|
} catch {
|
|
35569
35626
|
}
|
|
35570
35627
|
}
|
|
35571
35628
|
for (const f of PROOFS_TEMPLATE_FILES) {
|
|
35572
35629
|
const rel = `${PROOFS_DIR}/${f.path}`;
|
|
35573
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
35630
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
|
|
35574
35631
|
const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
|
|
35575
35632
|
if (current.ok && current.content === f.content) {
|
|
35576
35633
|
kept.push(rel);
|
|
@@ -35583,8 +35640,8 @@ function scaffoldProofs(root) {
|
|
|
35583
35640
|
[`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
|
|
35584
35641
|
[`${MODELS_DIR}/README.md`, MODELS_README]
|
|
35585
35642
|
]) {
|
|
35586
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
35587
|
-
if (existsNoFollow((0,
|
|
35643
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
|
|
35644
|
+
if (existsNoFollow((0, import_node_path42.join)(root, rel))) {
|
|
35588
35645
|
kept.push(rel);
|
|
35589
35646
|
continue;
|
|
35590
35647
|
}
|
|
@@ -35595,7 +35652,7 @@ function scaffoldProofs(root) {
|
|
|
35595
35652
|
}
|
|
35596
35653
|
function existsNoFollow(abs) {
|
|
35597
35654
|
try {
|
|
35598
|
-
(0,
|
|
35655
|
+
(0, import_node_fs57.lstatSync)(abs);
|
|
35599
35656
|
return true;
|
|
35600
35657
|
} catch {
|
|
35601
35658
|
return false;
|
|
@@ -35853,16 +35910,17 @@ function renderReport(r) {
|
|
|
35853
35910
|
|
|
35854
35911
|
// src/lib/prove/runner.ts
|
|
35855
35912
|
function verityLeanHome(env = process.env) {
|
|
35856
|
-
return env.VERITY_LEAN_HOME ?? (0,
|
|
35913
|
+
return env.VERITY_LEAN_HOME ?? (0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
|
|
35857
35914
|
}
|
|
35858
35915
|
function findToolchain(env = process.env) {
|
|
35859
|
-
const managedBin = (0,
|
|
35860
|
-
const elanBin = (0,
|
|
35861
|
-
const
|
|
35916
|
+
const managedBin = (0, import_node_path43.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
|
|
35917
|
+
const elanBin = (0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
|
|
35918
|
+
const elanHas = (0, import_node_fs58.existsSync)((0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
|
|
35919
|
+
const userPath = (env.PATH ?? "").split(import_node_path43.delimiter).filter((d) => d && (elanHas || (0, import_node_path43.resolve)(d) !== (0, import_node_path43.resolve)(elanBin)));
|
|
35920
|
+
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path43.delimiter);
|
|
35862
35921
|
const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
|
|
35863
|
-
const elanHas = (0, import_node_fs57.existsSync)((0, import_node_path42.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
|
|
35864
35922
|
const exe = process.platform === "win32" ? "lake.exe" : "lake";
|
|
35865
|
-
const candidates2 = [(0,
|
|
35923
|
+
const candidates2 = [(0, import_node_path43.join)(managedBin, exe), ...elanHas ? [(0, import_node_path43.join)(elanBin, exe)] : [], exe];
|
|
35866
35924
|
for (const candidate of candidates2) {
|
|
35867
35925
|
try {
|
|
35868
35926
|
(0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
|
|
@@ -35937,53 +35995,80 @@ function runAsync(tc, cwd, args2, timeoutMs) {
|
|
|
35937
35995
|
}
|
|
35938
35996
|
var DEFAULT_BUILD_TIMEOUT_MS = 10 * 6e4;
|
|
35939
35997
|
var DEFAULT_CHECK_TIMEOUT_MS = 12e4;
|
|
35998
|
+
function proofsWorkspaceProblem(root) {
|
|
35999
|
+
for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
|
|
36000
|
+
let st;
|
|
36001
|
+
try {
|
|
36002
|
+
st = (0, import_node_fs58.lstatSync)((0, import_node_path43.join)(root, rel));
|
|
36003
|
+
} catch {
|
|
36004
|
+
break;
|
|
36005
|
+
}
|
|
36006
|
+
if (st.isSymbolicLink()) return `${rel} is a symlink; Lean is not run through it`;
|
|
36007
|
+
}
|
|
36008
|
+
const r = runGitSync(root, ["ls-files", "-z", "--", PROOFS_DIR], { timeoutMs: 5e3 });
|
|
36009
|
+
if (!r.ok) return `could not confirm with git that ${PROOFS_DIR} holds no committed files; Lean is not run`;
|
|
36010
|
+
const tracked = r.stdout.split("\0").filter(Boolean);
|
|
36011
|
+
if (tracked.length > 0) {
|
|
36012
|
+
return `${tracked.length} file(s) under ${PROOFS_DIR} are tracked in git (e.g. ${tracked[0]}); Lean is not run on a workspace the repository supplies \u2014 untrack them with: git rm -r --cached ${PROOFS_DIR}`;
|
|
36013
|
+
}
|
|
36014
|
+
return null;
|
|
36015
|
+
}
|
|
36016
|
+
function refused(problem) {
|
|
36017
|
+
return { ok: false, stdout: "", stderr: problem, durationMs: 0, timedOut: false };
|
|
36018
|
+
}
|
|
35940
36019
|
function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
35941
|
-
|
|
36020
|
+
const problem = proofsWorkspaceProblem(root);
|
|
36021
|
+
if (problem) return refused(problem);
|
|
36022
|
+
return run2(tc, (0, import_node_path43.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
35942
36023
|
}
|
|
35943
|
-
function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
35944
|
-
|
|
36024
|
+
async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36025
|
+
const problem = proofsWorkspaceProblem(root);
|
|
36026
|
+
if (problem) return refused(problem);
|
|
36027
|
+
return runAsync(tc, (0, import_node_path43.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
35945
36028
|
}
|
|
35946
36029
|
function isModelInRoot(modelsAbs, rel) {
|
|
35947
|
-
if (!rel.endsWith(".lean") || (0,
|
|
36030
|
+
if (!rel.endsWith(".lean") || (0, import_node_path43.isAbsolute)(rel) || rel.startsWith("..")) return false;
|
|
35948
36031
|
return statRegularInRoot(modelsAbs, rel).ok;
|
|
35949
36032
|
}
|
|
35950
36033
|
function resolveModelFile(root, arg) {
|
|
35951
|
-
const modelsAbs = (0,
|
|
35952
|
-
const asPath = (0,
|
|
36034
|
+
const modelsAbs = (0, import_node_path43.join)(root, MODELS_DIR);
|
|
36035
|
+
const asPath = (0, import_node_path43.relative)(modelsAbs, (0, import_node_path43.isAbsolute)(arg) ? arg : (0, import_node_path43.resolve)(root, arg));
|
|
35953
36036
|
const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
|
|
35954
36037
|
for (const rel of candidates2) {
|
|
35955
|
-
if (isModelInRoot(modelsAbs, rel)) return (0,
|
|
36038
|
+
if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path43.join)(modelsAbs, rel);
|
|
35956
36039
|
}
|
|
35957
36040
|
return null;
|
|
35958
36041
|
}
|
|
35959
36042
|
function listModelFiles(root) {
|
|
35960
|
-
const modelsAbs = (0,
|
|
35961
|
-
if (!(0,
|
|
35962
|
-
return (0,
|
|
36043
|
+
const modelsAbs = (0, import_node_path43.join)(root, MODELS_DIR);
|
|
36044
|
+
if (!(0, import_node_fs58.existsSync)(modelsAbs)) return [];
|
|
36045
|
+
return (0, import_node_fs58.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path43.join)(modelsAbs, f));
|
|
35963
36046
|
}
|
|
35964
36047
|
function trimDiagnostics(text) {
|
|
35965
36048
|
return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
|
|
35966
36049
|
}
|
|
35967
36050
|
function checkModel(tc, root, modelFile, opts = {}) {
|
|
35968
|
-
const proofsAbs = (0,
|
|
35969
|
-
const rel = (0,
|
|
35970
|
-
const
|
|
36051
|
+
const proofsAbs = (0, import_node_path43.join)(root, PROOFS_DIR);
|
|
36052
|
+
const rel = (0, import_node_path43.relative)(proofsAbs, modelFile);
|
|
36053
|
+
const problem = proofsWorkspaceProblem(root);
|
|
36054
|
+
const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
35971
36055
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
35972
36056
|
}
|
|
35973
36057
|
async function checkModelAsync(tc, root, modelFile, opts = {}) {
|
|
35974
|
-
const proofsAbs = (0,
|
|
35975
|
-
const rel = (0,
|
|
35976
|
-
const
|
|
36058
|
+
const proofsAbs = (0, import_node_path43.join)(root, PROOFS_DIR);
|
|
36059
|
+
const rel = (0, import_node_path43.relative)(proofsAbs, modelFile);
|
|
36060
|
+
const problem = proofsWorkspaceProblem(root);
|
|
36061
|
+
const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
35977
36062
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
35978
36063
|
}
|
|
35979
36064
|
function toReport(res, root, modelFile, timeoutMs) {
|
|
35980
36065
|
const parsed = parseVerityLines(res.stdout);
|
|
35981
36066
|
const combined = `${res.stdout}
|
|
35982
36067
|
${res.stderr}`;
|
|
35983
|
-
const name2 = parsed.header?.model ?? (0,
|
|
36068
|
+
const name2 = parsed.header?.model ?? (0, import_node_path43.basename)(modelFile, ".lean");
|
|
35984
36069
|
const report = {
|
|
35985
36070
|
model: name2,
|
|
35986
|
-
file: (0,
|
|
36071
|
+
file: (0, import_node_path43.relative)(root, modelFile),
|
|
35987
36072
|
ok: res.ok,
|
|
35988
36073
|
header: parsed.header,
|
|
35989
36074
|
properties: parsed.properties,
|
|
@@ -36028,33 +36113,18 @@ function writeResult(root, report) {
|
|
|
36028
36113
|
function isCrashTrace(trace) {
|
|
36029
36114
|
return trace.some((s) => /\b(crash\w*|kill\w*|restart\w*|interrupt\w*|power|abort\w*|process (dies|exit\w*)|lost (reply|response))\b/i.test(s));
|
|
36030
36115
|
}
|
|
36031
|
-
var SEVERITY_BY_IMPACT = {
|
|
36032
|
-
money: "high",
|
|
36033
|
-
access: "high",
|
|
36034
|
-
data: "high",
|
|
36035
|
-
external: "high",
|
|
36036
|
-
count: "medium",
|
|
36037
|
-
cache: "medium",
|
|
36038
|
-
internal: "medium",
|
|
36039
|
-
// A reproduced finding always has a real code; 'none' here is a malformed answer, so it blocks.
|
|
36040
|
-
none: "high"
|
|
36041
|
-
};
|
|
36042
|
-
function formalSeverity(f) {
|
|
36043
|
-
return f.impact && SEVERITY_BY_IMPACT[f.impact] || "high";
|
|
36044
|
-
}
|
|
36045
36116
|
function mergeFormalFindings(response, outcome, pushedFiles) {
|
|
36046
|
-
if (!outcome) return { blocking: 0
|
|
36117
|
+
if (!outcome) return { blocking: 0 };
|
|
36047
36118
|
const norm2 = (p) => p.replace(/\\/g, "/");
|
|
36048
36119
|
const pushed = new Set(pushedFiles.map(norm2));
|
|
36049
|
-
const
|
|
36050
|
-
if (
|
|
36051
|
-
const blocking = reproduced.filter((f) => formalSeverity(f) === "high");
|
|
36120
|
+
const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file)));
|
|
36121
|
+
if (blocking.length === 0) return { blocking: 0 };
|
|
36052
36122
|
const existing = Array.isArray(response.findings) ? response.findings : [];
|
|
36053
36123
|
response.findings = [
|
|
36054
36124
|
...existing,
|
|
36055
|
-
...
|
|
36125
|
+
...blocking.map((f) => ({
|
|
36056
36126
|
pattern_id: "formal-counterexample",
|
|
36057
|
-
severity:
|
|
36127
|
+
severity: "high",
|
|
36058
36128
|
scope: "change",
|
|
36059
36129
|
file: f.file,
|
|
36060
36130
|
line: outcome.target?.lines?.from ?? null,
|
|
@@ -36062,15 +36132,14 @@ function mergeFormalFindings(response, outcome, pushedFiles) {
|
|
|
36062
36132
|
// as a title it read backwards (e2e, 2026-09-26). A trace that needs a
|
|
36063
36133
|
// crash between two writes is labelled: reproducing it means injecting
|
|
36064
36134
|
// the crash, so it is a crash-consistency finding, not a race.
|
|
36065
|
-
title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code
|
|
36135
|
+
title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code`,
|
|
36066
36136
|
description: terminalText(f.reason ?? "", 2e3),
|
|
36067
36137
|
fix: { description: `Trace: ${terminalText(f.trace.join(" \u2192 ") || "(initial state)", 2e3)}. Replay: ${terminalText(f.reason ?? "reproduced in the container", 2e3)}` },
|
|
36068
36138
|
source: "formal"
|
|
36069
36139
|
}))
|
|
36070
36140
|
];
|
|
36071
|
-
if (
|
|
36072
|
-
|
|
36073
|
-
return { blocking: blocking.length, warning: reproduced.length - blocking.length };
|
|
36141
|
+
if (response.gate_decision !== "FAIL") response.gate_decision = "FAIL";
|
|
36142
|
+
return { blocking: blocking.length };
|
|
36074
36143
|
}
|
|
36075
36144
|
|
|
36076
36145
|
// src/lib/prove/scalpel.ts
|
|
@@ -36237,20 +36306,28 @@ function isEligible(s, largePush) {
|
|
|
36237
36306
|
function intersects(a, ranges) {
|
|
36238
36307
|
return ranges.some((b) => a.from <= b.to && b.from <= a.to);
|
|
36239
36308
|
}
|
|
36309
|
+
function isLocalState(root, rel) {
|
|
36310
|
+
return repoControlled(root, rel) === null;
|
|
36311
|
+
}
|
|
36312
|
+
function nonNegative(v) {
|
|
36313
|
+
return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
|
|
36314
|
+
}
|
|
36240
36315
|
function readLedger(root) {
|
|
36241
36316
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
36242
36317
|
const empty = { day: today, models: 0, costUsd: 0 };
|
|
36318
|
+
if (!isLocalState(root, AUTO_LEDGER)) return empty;
|
|
36243
36319
|
const read2 = readRegularFileInRoot(root, AUTO_LEDGER, 4096);
|
|
36244
36320
|
if (!read2.ok) return empty;
|
|
36245
36321
|
try {
|
|
36246
36322
|
const o = JSON.parse(read2.content);
|
|
36247
36323
|
if (o.day !== today || typeof o.models !== "number") return empty;
|
|
36248
|
-
return { day: today, models: o.models, costUsd:
|
|
36324
|
+
return { day: today, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
|
|
36249
36325
|
} catch {
|
|
36250
36326
|
return empty;
|
|
36251
36327
|
}
|
|
36252
36328
|
}
|
|
36253
36329
|
function writeLedger(root, l) {
|
|
36330
|
+
if (!isLocalState(root, AUTO_LEDGER)) return;
|
|
36254
36331
|
try {
|
|
36255
36332
|
writeFileInRootNoFollow(root, AUTO_LEDGER, JSON.stringify(l) + "\n");
|
|
36256
36333
|
} catch {
|
|
@@ -36263,6 +36340,7 @@ function addLedgerCost(root, usd) {
|
|
|
36263
36340
|
}
|
|
36264
36341
|
var FINDINGS_FILE = `${PROOFS_DIR}/.results/.findings.json`;
|
|
36265
36342
|
function readPersistedFindings(root) {
|
|
36343
|
+
if (!isLocalState(root, FINDINGS_FILE)) return [];
|
|
36266
36344
|
const read2 = readRegularFileInRoot(root, FINDINGS_FILE, 256 * 1024);
|
|
36267
36345
|
if (!read2.ok) return [];
|
|
36268
36346
|
try {
|
|
@@ -36286,6 +36364,7 @@ function waiveFormalFindings(root, file, reason) {
|
|
|
36286
36364
|
return n;
|
|
36287
36365
|
}
|
|
36288
36366
|
function writePersistedFindings(root, findings) {
|
|
36367
|
+
if (!isLocalState(root, FINDINGS_FILE)) return;
|
|
36289
36368
|
try {
|
|
36290
36369
|
writeFileInRootNoFollow(root, FINDINGS_FILE, JSON.stringify({ findings: findings.slice(0, 50) }, null, 2) + "\n");
|
|
36291
36370
|
} catch {
|
|
@@ -36379,9 +36458,7 @@ async function runFormalPhase(input) {
|
|
|
36379
36458
|
symbol: f.symbol,
|
|
36380
36459
|
verdict: "reproduced",
|
|
36381
36460
|
reason: f.waived ? `waived ${f.waived.at.slice(0, 10)}: ${f.waived.reason} (standing since ${f.at.slice(0, 10)}; the file has not changed)` : `${f.reason ?? "reproduced on the real code"} (standing since ${f.at.slice(0, 10)}; the file has not changed)`,
|
|
36382
|
-
...f.waived ? { waived: true } : {}
|
|
36383
|
-
// A hand-edited file cannot invent a code: unknown values read as absent (HIGH).
|
|
36384
|
-
...isImpact(f.impact) ? { impact: f.impact } : {}
|
|
36461
|
+
...f.waived ? { waived: true } : {}
|
|
36385
36462
|
});
|
|
36386
36463
|
}
|
|
36387
36464
|
}
|
|
@@ -36420,6 +36497,7 @@ async function runFormalPhase(input) {
|
|
|
36420
36497
|
return done({ status: "skipped", skip: "not-eligible", detail: `${best.file}: ${isEligible(best, largePush).why}` });
|
|
36421
36498
|
}
|
|
36422
36499
|
const ranked = await deps.rank(eligible, root, input.changedLines);
|
|
36500
|
+
if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
|
|
36423
36501
|
if (ranked.ok) spend(ranked);
|
|
36424
36502
|
candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)) }));
|
|
36425
36503
|
if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
|
|
@@ -36560,7 +36638,7 @@ async function runFormalPhase(input) {
|
|
|
36560
36638
|
modelName = gen.name;
|
|
36561
36639
|
const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
|
|
36562
36640
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
36563
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
36641
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path44.join)(root, rel);
|
|
36564
36642
|
progress.model = { name: gen.name, file: rel, rounds: round };
|
|
36565
36643
|
progress.step = "check";
|
|
36566
36644
|
report = await deps.check(root, abs);
|
|
@@ -36654,7 +36732,7 @@ async function runFormalPhase(input) {
|
|
|
36654
36732
|
continue;
|
|
36655
36733
|
}
|
|
36656
36734
|
const verdict = r.verdict === "reproduced" ? "reproduced" : r.verdict === "diverged" ? "diverged" : r.verdict === "unreplayable" ? "model-only" : "unverified";
|
|
36657
|
-
findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0
|
|
36735
|
+
findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0 });
|
|
36658
36736
|
}
|
|
36659
36737
|
const reproduced = findings.filter((f) => f.verdict === "reproduced");
|
|
36660
36738
|
if (reproduced.length > 0 && !cancelled()) {
|
|
@@ -36662,7 +36740,7 @@ async function runFormalPhase(input) {
|
|
|
36662
36740
|
const others = readPersistedFindings(root).filter((f) => f.file !== top.file);
|
|
36663
36741
|
writePersistedFindings(root, [
|
|
36664
36742
|
...others,
|
|
36665
|
-
...reproduced.map((f) => ({ file: f.file, symbol: f.symbol, sha256: sha2562, property: f.property, desc: f.desc, kind: f.kind, trace: f.trace, model: modelName, reason: f.reason, ...
|
|
36743
|
+
...reproduced.map((f) => ({ file: f.file, symbol: f.symbol, sha256: sha2562, property: f.property, desc: f.desc, kind: f.kind, trace: f.trace, model: modelName, reason: f.reason, ...lines ? { lines } : {}, at: now }))
|
|
36666
36744
|
]);
|
|
36667
36745
|
}
|
|
36668
36746
|
const clean2 = findings.every((f) => f.verdict === "diverged");
|
|
@@ -36682,7 +36760,7 @@ async function runFormalPhase(input) {
|
|
|
36682
36760
|
return done({
|
|
36683
36761
|
status: "checked",
|
|
36684
36762
|
target,
|
|
36685
|
-
model: { name: modelName, file: (0,
|
|
36763
|
+
model: { name: modelName, file: (0, import_node_path44.relative)(root, (0, import_node_path44.join)(root, modelFile)), rounds },
|
|
36686
36764
|
properties: report.properties,
|
|
36687
36765
|
findings
|
|
36688
36766
|
});
|
|
@@ -36745,7 +36823,7 @@ async function generateAndCheck(root, req, opts) {
|
|
|
36745
36823
|
}
|
|
36746
36824
|
const rel = `${dir}/${gen.name}.lean`;
|
|
36747
36825
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
36748
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
36826
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path44.join)(root, rel);
|
|
36749
36827
|
const report = await opts.deps.check(root, abs);
|
|
36750
36828
|
const abstracts = report.header?.abstracts ?? [];
|
|
36751
36829
|
const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
|
|
@@ -36783,6 +36861,8 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
|
|
|
36783
36861
|
const apiKey = direct ? env.OPENAI_API_KEY : void 0;
|
|
36784
36862
|
const toolchain = findToolchain(env);
|
|
36785
36863
|
if (!toolchain) return { ok: false, skip: "no-toolchain" };
|
|
36864
|
+
const untrusted = proofsWorkspaceProblem(root);
|
|
36865
|
+
if (untrusted) return { ok: false, skip: "workspace-untrusted", detail: untrusted.slice(0, 200) };
|
|
36786
36866
|
try {
|
|
36787
36867
|
scaffoldProofs(root);
|
|
36788
36868
|
} catch (err2) {
|
|
@@ -36872,7 +36952,7 @@ var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
|
36872
36952
|
var WRITERS_BUDGET_MS = 1500;
|
|
36873
36953
|
var EXCERPT_MAX_LINES2 = 30;
|
|
36874
36954
|
var GUARD_BLOCK_CAP = 2;
|
|
36875
|
-
var GUARD_ITER_FILE = (0,
|
|
36955
|
+
var GUARD_ITER_FILE = (0, import_node_path45.join)(VERITY_DIR, ".guard-iteration");
|
|
36876
36956
|
function readPreToolUseStdin() {
|
|
36877
36957
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
36878
36958
|
return new Promise((resolve8) => {
|
|
@@ -36917,7 +36997,7 @@ function readPreToolUseStdin() {
|
|
|
36917
36997
|
}
|
|
36918
36998
|
function readIterMap() {
|
|
36919
36999
|
try {
|
|
36920
|
-
const raw = JSON.parse((0,
|
|
37000
|
+
const raw = JSON.parse((0, import_node_fs59.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
36921
37001
|
if (raw && typeof raw === "object") {
|
|
36922
37002
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
36923
37003
|
return { [raw.moment]: raw.count };
|
|
@@ -36937,10 +37017,10 @@ function readIter(moment) {
|
|
|
36937
37017
|
}
|
|
36938
37018
|
function writeIter(moment, count) {
|
|
36939
37019
|
try {
|
|
36940
|
-
(0,
|
|
37020
|
+
(0, import_node_fs59.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
36941
37021
|
const map = readIterMap();
|
|
36942
37022
|
map[moment] = count;
|
|
36943
|
-
(0,
|
|
37023
|
+
(0, import_node_fs59.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
36944
37024
|
} catch {
|
|
36945
37025
|
}
|
|
36946
37026
|
}
|
|
@@ -36950,10 +37030,10 @@ function resetIter(moment) {
|
|
|
36950
37030
|
if (!(moment in map)) return;
|
|
36951
37031
|
delete map[moment];
|
|
36952
37032
|
if (Object.keys(map).length === 0) {
|
|
36953
|
-
if ((0,
|
|
37033
|
+
if ((0, import_node_fs59.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs59.unlinkSync)(GUARD_ITER_FILE);
|
|
36954
37034
|
} else {
|
|
36955
|
-
(0,
|
|
36956
|
-
(0,
|
|
37035
|
+
(0, import_node_fs59.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37036
|
+
(0, import_node_fs59.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
36957
37037
|
}
|
|
36958
37038
|
} catch {
|
|
36959
37039
|
}
|
|
@@ -37023,7 +37103,7 @@ function hasBlockingFinding(response, sentFiles) {
|
|
|
37023
37103
|
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
37024
37104
|
const analyzable = filterAnalyzable(files);
|
|
37025
37105
|
const securityFiles = filterSecurity(files);
|
|
37026
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
37106
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs59.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
37027
37107
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
37028
37108
|
const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
|
|
37029
37109
|
const requestBody = {
|
|
@@ -37400,8 +37480,6 @@ async function runGuard(opts, globals) {
|
|
|
37400
37480
|
rounds: formalOutcome.model?.rounds ?? null,
|
|
37401
37481
|
properties: formalOutcome.properties?.map((p) => `${p.id}:${p.result}`) ?? [],
|
|
37402
37482
|
findings: formalOutcome.findings.map((f) => `${f.property}:${f.verdict}`),
|
|
37403
|
-
// Decision 82: the replay's impact code per reproduced finding; count/cache/internal warn, the rest block.
|
|
37404
|
-
impacts: formalOutcome.findings.filter((f) => f.impact).map((f) => `${f.property}:${f.impact}`),
|
|
37405
37483
|
// Decision 81: what each property rests on (a rule, or "line"), what was
|
|
37406
37484
|
// sent back or dropped as ungrounded, and which counterexamples lack their
|
|
37407
37485
|
// property's trigger (shadow). Ids and rule names only, never code.
|
|
@@ -37643,7 +37721,7 @@ function registerIgnoreCommand(program2) {
|
|
|
37643
37721
|
|
|
37644
37722
|
// src/commands/waive.ts
|
|
37645
37723
|
var import_node_crypto19 = require("node:crypto");
|
|
37646
|
-
var
|
|
37724
|
+
var import_node_fs60 = require("node:fs");
|
|
37647
37725
|
function registerWaiveCommand(program2) {
|
|
37648
37726
|
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) => {
|
|
37649
37727
|
const globals = program2.opts();
|
|
@@ -37672,7 +37750,7 @@ function registerWaiveCommand(program2) {
|
|
|
37672
37750
|
if (opts.file) {
|
|
37673
37751
|
body2.file = opts.file;
|
|
37674
37752
|
try {
|
|
37675
|
-
body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0,
|
|
37753
|
+
body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0, import_node_fs60.readFileSync)(opts.file)).digest("hex");
|
|
37676
37754
|
} catch {
|
|
37677
37755
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
37678
37756
|
process.exit(1);
|
|
@@ -37697,10 +37775,10 @@ function registerWaiveCommand(program2) {
|
|
|
37697
37775
|
}
|
|
37698
37776
|
|
|
37699
37777
|
// src/commands/init.ts
|
|
37700
|
-
var
|
|
37778
|
+
var import_node_fs65 = require("node:fs");
|
|
37701
37779
|
var import_promises20 = require("node:fs/promises");
|
|
37702
37780
|
var import_yaml6 = __toESM2(require_dist());
|
|
37703
|
-
var
|
|
37781
|
+
var import_node_path49 = require("node:path");
|
|
37704
37782
|
var import_node_child_process19 = require("node:child_process");
|
|
37705
37783
|
|
|
37706
37784
|
// src/lib/banner.ts
|
|
@@ -37779,7 +37857,7 @@ function printPhase(n, of, title, subtitle) {
|
|
|
37779
37857
|
}
|
|
37780
37858
|
|
|
37781
37859
|
// src/commands/doctor.ts
|
|
37782
|
-
var
|
|
37860
|
+
var import_node_fs61 = require("node:fs");
|
|
37783
37861
|
|
|
37784
37862
|
// src/lib/prereqs.ts
|
|
37785
37863
|
var import_node_child_process16 = require("node:child_process");
|
|
@@ -37987,11 +38065,11 @@ async function buildReport() {
|
|
|
37987
38065
|
const hooks = wiring.status;
|
|
37988
38066
|
const provenance = cliProvenance();
|
|
37989
38067
|
const telemetry = await checkTelemetry();
|
|
37990
|
-
const hasConfig = (0,
|
|
38068
|
+
const hasConfig = (0, import_node_fs61.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
37991
38069
|
const artifacts = {
|
|
37992
|
-
standard: (0,
|
|
38070
|
+
standard: (0, import_node_fs61.existsSync)(projectPath(STANDARD_FILE)),
|
|
37993
38071
|
analysisConfig: hasConfig,
|
|
37994
|
-
verityMd: (0,
|
|
38072
|
+
verityMd: (0, import_node_fs61.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
37995
38073
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
37996
38074
|
};
|
|
37997
38075
|
const next = [];
|
|
@@ -38121,9 +38199,11 @@ function registerDoctorCommand(program2) {
|
|
|
38121
38199
|
printInfo(` Stop (verity analyze): ${report.hooks.stop ? plugin ? "on (plugin)" : "on" : "off"}`);
|
|
38122
38200
|
printInfo(` Git-moment gate: ${report.hooks.guardOn.length ? report.hooks.guardOn.join(", ") : "off"}`);
|
|
38123
38201
|
{
|
|
38124
|
-
const
|
|
38202
|
+
const cfg = readProjectConfig();
|
|
38203
|
+
const formal = cfg.formal === "push";
|
|
38125
38204
|
const tc = formal ? findToolchain() : null;
|
|
38126
38205
|
printInfo(` Formal verification (push): ${formal ? `on, Lean ${tc ? "\u2713" : "MISSING \u2014 verity lean install"} (ranking, model writing and replay run on the Verity service with your login)` : "off"}`);
|
|
38206
|
+
if (cfg.formal_refused) printWarn(` ${formalRefusalMessage(cfg.formal_refused)}`);
|
|
38127
38207
|
}
|
|
38128
38208
|
printInfo(` Infra (intent/baseline/compact/session-end): ${[report.hooks.intent, report.hooks.baseline, report.hooks.compact, report.hooks.sessionEnd].filter(Boolean).length}/4`);
|
|
38129
38209
|
printInfo(`Telemetry: ${report.telemetry.enabled ? `enabled \u2192 ${report.telemetry.endpoint}` : "disabled"}`);
|
|
@@ -38148,8 +38228,8 @@ function registerDoctorCommand(program2) {
|
|
|
38148
38228
|
}
|
|
38149
38229
|
|
|
38150
38230
|
// src/commands/migrate.ts
|
|
38151
|
-
var
|
|
38152
|
-
var
|
|
38231
|
+
var import_node_fs62 = require("node:fs");
|
|
38232
|
+
var import_node_path46 = require("node:path");
|
|
38153
38233
|
var import_node_child_process17 = require("node:child_process");
|
|
38154
38234
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
38155
38235
|
function defaultNpmRemover(pkg) {
|
|
@@ -38186,12 +38266,12 @@ async function runMigration(opts = {}) {
|
|
|
38186
38266
|
return { actions, migrated: actions.length > 0 };
|
|
38187
38267
|
}
|
|
38188
38268
|
function migrateProjectDir(root, actions) {
|
|
38189
|
-
const gateDir = (0,
|
|
38190
|
-
const verityDir = (0,
|
|
38191
|
-
if ((0,
|
|
38269
|
+
const gateDir = (0, import_node_path46.join)(root, ".gate");
|
|
38270
|
+
const verityDir = (0, import_node_path46.join)(root, ".verity");
|
|
38271
|
+
if ((0, import_node_fs62.existsSync)(gateDir) && !(0, import_node_fs62.existsSync)(verityDir)) {
|
|
38192
38272
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
38193
38273
|
}
|
|
38194
|
-
if ((0,
|
|
38274
|
+
if ((0, import_node_fs62.existsSync)(gateDir) && (0, import_node_fs62.existsSync)(verityDir)) {
|
|
38195
38275
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
38196
38276
|
}
|
|
38197
38277
|
return false;
|
|
@@ -38212,13 +38292,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
38212
38292
|
}
|
|
38213
38293
|
}
|
|
38214
38294
|
if (moved) {
|
|
38215
|
-
if ((0,
|
|
38295
|
+
if ((0, import_node_fs62.existsSync)(gateDir)) {
|
|
38216
38296
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
38217
38297
|
if (carried > 0) {
|
|
38218
38298
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
38219
38299
|
}
|
|
38220
38300
|
try {
|
|
38221
|
-
(0,
|
|
38301
|
+
(0, import_node_fs62.rmSync)(gateDir, { recursive: true, force: true });
|
|
38222
38302
|
} catch {
|
|
38223
38303
|
}
|
|
38224
38304
|
}
|
|
@@ -38234,18 +38314,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
38234
38314
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
38235
38315
|
}
|
|
38236
38316
|
try {
|
|
38237
|
-
(0,
|
|
38317
|
+
(0, import_node_fs62.rmSync)(gateDir, { recursive: true, force: true });
|
|
38238
38318
|
} catch {
|
|
38239
38319
|
}
|
|
38240
38320
|
return carried > 0;
|
|
38241
38321
|
}
|
|
38242
38322
|
function migrateGlobalCredentials(home, actions) {
|
|
38243
38323
|
if (!home) return;
|
|
38244
|
-
const gateCreds = (0,
|
|
38245
|
-
const verityCreds = (0,
|
|
38246
|
-
if (!(0,
|
|
38247
|
-
if (!(0,
|
|
38248
|
-
(0,
|
|
38324
|
+
const gateCreds = (0, import_node_path46.join)(home, ".gate", "credentials");
|
|
38325
|
+
const verityCreds = (0, import_node_path46.join)(home, ".verity", "credentials");
|
|
38326
|
+
if (!(0, import_node_fs62.existsSync)(gateCreds)) return;
|
|
38327
|
+
if (!(0, import_node_fs62.existsSync)(verityCreds)) {
|
|
38328
|
+
(0, import_node_fs62.mkdirSync)((0, import_node_path46.join)(home, ".verity"), { recursive: true });
|
|
38249
38329
|
moveFile(gateCreds, verityCreds);
|
|
38250
38330
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
38251
38331
|
return;
|
|
@@ -38267,8 +38347,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
38267
38347
|
}
|
|
38268
38348
|
}
|
|
38269
38349
|
async function migrateClaudeMd(root, actions) {
|
|
38270
|
-
const claudeMd = (0,
|
|
38271
|
-
const hadLegacyBlock = (0,
|
|
38350
|
+
const claudeMd = (0, import_node_path46.join)(root, "CLAUDE.md");
|
|
38351
|
+
const hadLegacyBlock = (0, import_node_fs62.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
38272
38352
|
if (!hadLegacyBlock) return;
|
|
38273
38353
|
try {
|
|
38274
38354
|
await ensureClaudeMdPointer(root);
|
|
@@ -38278,9 +38358,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
38278
38358
|
}
|
|
38279
38359
|
}
|
|
38280
38360
|
function migrateStandardFile(root, actions) {
|
|
38281
|
-
const gateMd = (0,
|
|
38282
|
-
const verityMd = (0,
|
|
38283
|
-
if (!(0,
|
|
38361
|
+
const gateMd = (0, import_node_path46.join)(root, "GATE.md");
|
|
38362
|
+
const verityMd = (0, import_node_path46.join)(root, "VERITY.md");
|
|
38363
|
+
if (!(0, import_node_fs62.existsSync)(gateMd) || (0, import_node_fs62.existsSync)(verityMd)) return;
|
|
38284
38364
|
let moved = false;
|
|
38285
38365
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
38286
38366
|
try {
|
|
@@ -38292,12 +38372,12 @@ function migrateStandardFile(root, actions) {
|
|
|
38292
38372
|
if (!moved) moveFile(gateMd, verityMd);
|
|
38293
38373
|
const content = readFileSyncSafe(verityMd);
|
|
38294
38374
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
38295
|
-
if (refreshed !== content) (0,
|
|
38375
|
+
if (refreshed !== content) (0, import_node_fs62.writeFileSync)(verityMd, refreshed);
|
|
38296
38376
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
38297
38377
|
}
|
|
38298
38378
|
async function migrateTelemetryHeaders(root, actions) {
|
|
38299
|
-
const file = (0,
|
|
38300
|
-
if (!(0,
|
|
38379
|
+
const file = (0, import_node_path46.join)(root, ".claude", "settings.local.json");
|
|
38380
|
+
if (!(0, import_node_fs62.existsSync)(file)) return;
|
|
38301
38381
|
let settings;
|
|
38302
38382
|
try {
|
|
38303
38383
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -38345,14 +38425,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
38345
38425
|
}
|
|
38346
38426
|
if (toAppend.length > 0) {
|
|
38347
38427
|
const sep5 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
38348
|
-
(0,
|
|
38428
|
+
(0, import_node_fs62.writeFileSync)(verityCreds, verityContent + sep5 + toAppend.join("\n") + "\n");
|
|
38349
38429
|
}
|
|
38350
|
-
(0,
|
|
38430
|
+
(0, import_node_fs62.rmSync)(gateCreds, { force: true });
|
|
38351
38431
|
return toAppend.length;
|
|
38352
38432
|
}
|
|
38353
38433
|
function readFileSyncSafe(path) {
|
|
38354
38434
|
try {
|
|
38355
|
-
return (0,
|
|
38435
|
+
return (0, import_node_fs62.readFileSync)(path, "utf-8");
|
|
38356
38436
|
} catch {
|
|
38357
38437
|
return "";
|
|
38358
38438
|
}
|
|
@@ -38367,35 +38447,35 @@ function hasStagedChanges(root) {
|
|
|
38367
38447
|
}
|
|
38368
38448
|
function moveDir(from, to) {
|
|
38369
38449
|
try {
|
|
38370
|
-
(0,
|
|
38450
|
+
(0, import_node_fs62.renameSync)(from, to);
|
|
38371
38451
|
} catch (err2) {
|
|
38372
38452
|
if (err2.code !== "EXDEV") throw err2;
|
|
38373
|
-
(0,
|
|
38374
|
-
(0,
|
|
38453
|
+
(0, import_node_fs62.cpSync)(from, to, { recursive: true });
|
|
38454
|
+
(0, import_node_fs62.rmSync)(from, { recursive: true, force: true });
|
|
38375
38455
|
}
|
|
38376
38456
|
}
|
|
38377
38457
|
function moveFile(from, to) {
|
|
38378
38458
|
try {
|
|
38379
|
-
(0,
|
|
38459
|
+
(0, import_node_fs62.renameSync)(from, to);
|
|
38380
38460
|
} catch (err2) {
|
|
38381
38461
|
if (err2.code !== "EXDEV") throw err2;
|
|
38382
|
-
(0,
|
|
38383
|
-
(0,
|
|
38462
|
+
(0, import_node_fs62.cpSync)(from, to);
|
|
38463
|
+
(0, import_node_fs62.rmSync)(from, { force: true });
|
|
38384
38464
|
}
|
|
38385
38465
|
}
|
|
38386
38466
|
function carryLegacyContents(gateDir, verityDir) {
|
|
38387
38467
|
let copied = 0;
|
|
38388
38468
|
const walk2 = (relDir) => {
|
|
38389
|
-
const srcDir = (0,
|
|
38390
|
-
for (const entry of (0,
|
|
38391
|
-
const rel = relDir ? (0,
|
|
38392
|
-
const src = (0,
|
|
38393
|
-
const dest = (0,
|
|
38394
|
-
if ((0,
|
|
38469
|
+
const srcDir = (0, import_node_path46.join)(gateDir, relDir);
|
|
38470
|
+
for (const entry of (0, import_node_fs62.readdirSync)(srcDir)) {
|
|
38471
|
+
const rel = relDir ? (0, import_node_path46.join)(relDir, entry) : entry;
|
|
38472
|
+
const src = (0, import_node_path46.join)(gateDir, rel);
|
|
38473
|
+
const dest = (0, import_node_path46.join)(verityDir, rel);
|
|
38474
|
+
if ((0, import_node_fs62.statSync)(src).isDirectory()) {
|
|
38395
38475
|
walk2(rel);
|
|
38396
|
-
} else if (!(0,
|
|
38397
|
-
(0,
|
|
38398
|
-
(0,
|
|
38476
|
+
} else if (!(0, import_node_fs62.existsSync)(dest)) {
|
|
38477
|
+
(0, import_node_fs62.mkdirSync)((0, import_node_path46.dirname)(dest), { recursive: true });
|
|
38478
|
+
(0, import_node_fs62.cpSync)(src, dest);
|
|
38399
38479
|
copied++;
|
|
38400
38480
|
}
|
|
38401
38481
|
}
|
|
@@ -38404,22 +38484,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
38404
38484
|
return copied;
|
|
38405
38485
|
}
|
|
38406
38486
|
async function needsMigration(root = repoRoot()) {
|
|
38407
|
-
const gateDir = (0,
|
|
38408
|
-
const verityDir = (0,
|
|
38409
|
-
if ((0,
|
|
38410
|
-
if ((0,
|
|
38411
|
-
if ((0,
|
|
38487
|
+
const gateDir = (0, import_node_path46.join)(root, ".gate");
|
|
38488
|
+
const verityDir = (0, import_node_path46.join)(root, ".verity");
|
|
38489
|
+
if ((0, import_node_fs62.existsSync)(gateDir) && !(0, import_node_fs62.existsSync)(verityDir)) return true;
|
|
38490
|
+
if ((0, import_node_fs62.existsSync)(gateDir) && (0, import_node_fs62.existsSync)(verityDir)) {
|
|
38491
|
+
if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(gateDir, "credentials")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(verityDir, "credentials"))) {
|
|
38412
38492
|
return true;
|
|
38413
38493
|
}
|
|
38414
|
-
if ((0,
|
|
38494
|
+
if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(gateDir, "memory")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(verityDir, "memory"))) {
|
|
38415
38495
|
return true;
|
|
38416
38496
|
}
|
|
38417
38497
|
}
|
|
38418
|
-
const claudeMd = (0,
|
|
38419
|
-
if ((0,
|
|
38498
|
+
const claudeMd = (0, import_node_path46.join)(root, "CLAUDE.md");
|
|
38499
|
+
if ((0, import_node_fs62.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
38420
38500
|
return true;
|
|
38421
38501
|
}
|
|
38422
|
-
if ((0,
|
|
38502
|
+
if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(root, "GATE.md")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(root, "VERITY.md"))) {
|
|
38423
38503
|
return true;
|
|
38424
38504
|
}
|
|
38425
38505
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -38700,15 +38780,31 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
38700
38780
|
}
|
|
38701
38781
|
|
|
38702
38782
|
// src/lib/prove/lean-install.ts
|
|
38703
|
-
var
|
|
38783
|
+
var import_node_fs63 = require("node:fs");
|
|
38704
38784
|
var import_node_crypto20 = require("node:crypto");
|
|
38705
38785
|
var import_node_child_process18 = require("node:child_process");
|
|
38706
38786
|
var import_node_os10 = require("node:os");
|
|
38707
|
-
var
|
|
38787
|
+
var import_node_path47 = require("node:path");
|
|
38708
38788
|
var import_promises18 = require("node:stream/promises");
|
|
38709
38789
|
var import_node_stream = require("node:stream");
|
|
38710
38790
|
var RELEASES = "https://releases.lean-lang.org/lean4";
|
|
38711
38791
|
var LEAN_DOWNLOAD_SIZE = "\u2248800 MB download, 2.7 GB on disk";
|
|
38792
|
+
var DOWNLOAD_STALL_MS = 6e4;
|
|
38793
|
+
var LEAN_DISK_NEEDED_BYTES = 3.75 * 1024 ** 3;
|
|
38794
|
+
function freeBytes(dir) {
|
|
38795
|
+
let d = dir;
|
|
38796
|
+
for (let i2 = 0; i2 < 64; i2++) {
|
|
38797
|
+
try {
|
|
38798
|
+
const st = (0, import_node_fs63.statfsSync)(d);
|
|
38799
|
+
return Number(st.bavail) * Number(st.bsize);
|
|
38800
|
+
} catch {
|
|
38801
|
+
const up = (0, import_node_path47.join)(d, "..");
|
|
38802
|
+
if (up === d) return null;
|
|
38803
|
+
d = up;
|
|
38804
|
+
}
|
|
38805
|
+
}
|
|
38806
|
+
return null;
|
|
38807
|
+
}
|
|
38712
38808
|
var LEAN_ASSET_SHA256 = {
|
|
38713
38809
|
"v4.34.0": {
|
|
38714
38810
|
"lean-4.34.0-darwin.zip": "75a2a4b8e3d35680e8f51fae5a42c79702f463dd73ee1520fb61e5a9143e336c",
|
|
@@ -38724,7 +38820,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
|
|
|
38724
38820
|
function sha256File(path) {
|
|
38725
38821
|
return new Promise((resolve8, reject) => {
|
|
38726
38822
|
const hash = (0, import_node_crypto20.createHash)("sha256");
|
|
38727
|
-
(0,
|
|
38823
|
+
(0, import_node_fs63.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve8(hash.digest("hex"))).on("error", reject);
|
|
38728
38824
|
});
|
|
38729
38825
|
}
|
|
38730
38826
|
async function verifyDownload(zip, asset, version = pinnedVersion()) {
|
|
@@ -38744,7 +38840,7 @@ function leanAssetName(version = pinnedVersion()) {
|
|
|
38744
38840
|
return suffix ? `lean-${v}-${suffix}.zip` : null;
|
|
38745
38841
|
}
|
|
38746
38842
|
function pinnedVersionDir(env = process.env) {
|
|
38747
|
-
return (0,
|
|
38843
|
+
return (0, import_node_path47.join)(verityLeanHome(env), pinnedVersion());
|
|
38748
38844
|
}
|
|
38749
38845
|
function lakeBinary() {
|
|
38750
38846
|
return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
|
|
@@ -38755,29 +38851,44 @@ function unzip(zip, dest) {
|
|
|
38755
38851
|
for (const [cmd, args2] of attempts) {
|
|
38756
38852
|
try {
|
|
38757
38853
|
(0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
|
|
38758
|
-
if ((0,
|
|
38854
|
+
if ((0, import_node_fs63.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
|
|
38759
38855
|
errors.push(`${cmd}: produced nothing`);
|
|
38760
38856
|
} catch (err2) {
|
|
38761
38857
|
errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
|
|
38762
38858
|
try {
|
|
38763
|
-
for (const e of (0,
|
|
38859
|
+
for (const e of (0, import_node_fs63.readdirSync)(dest)) (0, import_node_fs63.rmSync)((0, import_node_path47.join)(dest, e), { recursive: true, force: true });
|
|
38764
38860
|
} catch {
|
|
38765
38861
|
}
|
|
38766
38862
|
}
|
|
38767
38863
|
}
|
|
38768
38864
|
return { ok: false, error: errors.join("; ") };
|
|
38769
38865
|
}
|
|
38770
|
-
async function download(url, dest, onProgress) {
|
|
38771
|
-
const
|
|
38772
|
-
|
|
38773
|
-
const
|
|
38774
|
-
|
|
38775
|
-
|
|
38776
|
-
|
|
38777
|
-
|
|
38778
|
-
|
|
38779
|
-
|
|
38780
|
-
|
|
38866
|
+
async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
|
|
38867
|
+
const ctrl = new AbortController();
|
|
38868
|
+
let timer;
|
|
38869
|
+
const arm = () => {
|
|
38870
|
+
clearTimeout(timer);
|
|
38871
|
+
timer = setTimeout(() => ctrl.abort(), stallMs);
|
|
38872
|
+
};
|
|
38873
|
+
arm();
|
|
38874
|
+
try {
|
|
38875
|
+
const res = await fetch(url, { redirect: "follow", signal: ctrl.signal });
|
|
38876
|
+
if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status}`);
|
|
38877
|
+
const total = Number(res.headers.get("content-length")) || null;
|
|
38878
|
+
let seen = 0;
|
|
38879
|
+
const stream = import_node_stream.Readable.fromWeb(res.body);
|
|
38880
|
+
stream.on("data", (chunk) => {
|
|
38881
|
+
arm();
|
|
38882
|
+
seen += chunk.length;
|
|
38883
|
+
onProgress(seen, total);
|
|
38884
|
+
});
|
|
38885
|
+
await (0, import_promises18.pipeline)(stream, (0, import_node_fs63.createWriteStream)(dest), { signal: ctrl.signal });
|
|
38886
|
+
} catch (err2) {
|
|
38887
|
+
if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
|
|
38888
|
+
throw err2;
|
|
38889
|
+
} finally {
|
|
38890
|
+
clearTimeout(timer);
|
|
38891
|
+
}
|
|
38781
38892
|
}
|
|
38782
38893
|
function inPlaceProgress(label2, write = (s) => process.stderr.write(s)) {
|
|
38783
38894
|
let active = false;
|
|
@@ -38815,10 +38926,16 @@ async function installLean(opts = {}) {
|
|
|
38815
38926
|
const dir = pinnedVersionDir(env);
|
|
38816
38927
|
const url = `${RELEASES}/${pinnedVersion()}/${asset}`;
|
|
38817
38928
|
const home = verityLeanHome(env);
|
|
38818
|
-
const
|
|
38819
|
-
|
|
38820
|
-
|
|
38821
|
-
|
|
38929
|
+
const free = freeBytes(home);
|
|
38930
|
+
const needed = opts.minFreeBytes ?? LEAN_DISK_NEEDED_BYTES;
|
|
38931
|
+
if (free !== null && free < needed) {
|
|
38932
|
+
const gb = (n) => (n / 1024 ** 3).toFixed(1);
|
|
38933
|
+
return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
|
|
38934
|
+
}
|
|
38935
|
+
const tmp = (0, import_node_path47.join)(home, ".tmp");
|
|
38936
|
+
(0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
|
|
38937
|
+
(0, import_node_fs63.mkdirSync)(tmp, { recursive: true });
|
|
38938
|
+
const zip = (0, import_node_path47.join)(tmp, asset);
|
|
38822
38939
|
say(`downloading ${url}`);
|
|
38823
38940
|
let lastPct = -1;
|
|
38824
38941
|
try {
|
|
@@ -38831,40 +38948,40 @@ async function installLean(opts = {}) {
|
|
|
38831
38948
|
}
|
|
38832
38949
|
});
|
|
38833
38950
|
} catch (err2) {
|
|
38834
|
-
(0,
|
|
38951
|
+
(0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
|
|
38835
38952
|
return { ok: false, error: err2.message };
|
|
38836
38953
|
}
|
|
38837
38954
|
say("verifying checksum");
|
|
38838
38955
|
const verified = await verifyDownload(zip, asset);
|
|
38839
38956
|
if (!verified.ok) {
|
|
38840
|
-
(0,
|
|
38957
|
+
(0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
|
|
38841
38958
|
return { ok: false, error: verified.error };
|
|
38842
38959
|
}
|
|
38843
38960
|
say("unpacking (this takes a minute)");
|
|
38844
|
-
const unpack = (0,
|
|
38845
|
-
(0,
|
|
38961
|
+
const unpack = (0, import_node_path47.join)(tmp, "unpack");
|
|
38962
|
+
(0, import_node_fs63.mkdirSync)(unpack);
|
|
38846
38963
|
const unpacked = unzip(zip, unpack);
|
|
38847
38964
|
if (!unpacked.ok) {
|
|
38848
|
-
(0,
|
|
38965
|
+
(0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
|
|
38849
38966
|
return { ok: false, error: `unpack failed: ${unpacked.error}` };
|
|
38850
38967
|
}
|
|
38851
|
-
const entries = (0,
|
|
38852
|
-
const top = entries.length === 1 && (0,
|
|
38853
|
-
if (!(0,
|
|
38854
|
-
(0,
|
|
38968
|
+
const entries = (0, import_node_fs63.readdirSync)(unpack);
|
|
38969
|
+
const top = entries.length === 1 && (0, import_node_fs63.statSync)((0, import_node_path47.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path47.join)(unpack, entries[0]) : unpack;
|
|
38970
|
+
if (!(0, import_node_fs63.existsSync)((0, import_node_path47.join)(top, "bin", lakeBinary()))) {
|
|
38971
|
+
(0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
|
|
38855
38972
|
return { ok: false, error: "the archive did not contain bin/lake" };
|
|
38856
38973
|
}
|
|
38857
|
-
(0,
|
|
38858
|
-
(0,
|
|
38859
|
-
(0,
|
|
38860
|
-
(0,
|
|
38974
|
+
(0, import_node_fs63.rmSync)(dir, { recursive: true, force: true });
|
|
38975
|
+
(0, import_node_fs63.mkdirSync)(home, { recursive: true });
|
|
38976
|
+
(0, import_node_fs63.renameSync)(top, dir);
|
|
38977
|
+
(0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
|
|
38861
38978
|
return { ok: true, dir };
|
|
38862
38979
|
}
|
|
38863
38980
|
|
|
38864
38981
|
// src/lib/remote-config.ts
|
|
38865
|
-
var
|
|
38982
|
+
var import_node_fs64 = require("node:fs");
|
|
38866
38983
|
var import_promises19 = require("node:fs/promises");
|
|
38867
|
-
var
|
|
38984
|
+
var import_node_path48 = require("node:path");
|
|
38868
38985
|
var import_yaml5 = __toESM2(require_dist());
|
|
38869
38986
|
var IGNORE_RIDER = "verityignore";
|
|
38870
38987
|
async function fetchRemoteSetup(opts) {
|
|
@@ -38909,7 +39026,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
38909
39026
|
written.push(STANDARD_FILE);
|
|
38910
39027
|
if (rider !== null) {
|
|
38911
39028
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
38912
|
-
if (!(0,
|
|
39029
|
+
if (!(0, import_node_fs64.existsSync)(localIgnore)) {
|
|
38913
39030
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
38914
39031
|
written.push(VERITYIGNORE_FILE);
|
|
38915
39032
|
} else {
|
|
@@ -38942,7 +39059,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
38942
39059
|
}
|
|
38943
39060
|
async function writeOut(relative6, body2) {
|
|
38944
39061
|
const target = projectPath(relative6);
|
|
38945
|
-
await (0, import_promises19.mkdir)((0,
|
|
39062
|
+
await (0, import_promises19.mkdir)((0, import_node_path48.dirname)(target), { recursive: true });
|
|
38946
39063
|
await (0, import_promises19.writeFile)(target, body2);
|
|
38947
39064
|
}
|
|
38948
39065
|
function describeRemote(found) {
|
|
@@ -39059,15 +39176,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
39059
39176
|
}
|
|
39060
39177
|
function resolveDataDir2() {
|
|
39061
39178
|
const candidates2 = [
|
|
39062
|
-
(0,
|
|
39179
|
+
(0, import_node_path49.join)(__dirname, "..", "data"),
|
|
39063
39180
|
// installed: node_modules/@codacy/verity-cli/data
|
|
39064
|
-
(0,
|
|
39181
|
+
(0, import_node_path49.join)(__dirname, "..", "..", "data"),
|
|
39065
39182
|
// edge case: nested resolution
|
|
39066
|
-
(0,
|
|
39183
|
+
(0, import_node_path49.join)(process.cwd(), "cli", "data")
|
|
39067
39184
|
// local dev: running from repo root
|
|
39068
39185
|
];
|
|
39069
39186
|
for (const candidate of candidates2) {
|
|
39070
|
-
if ((0,
|
|
39187
|
+
if ((0, import_node_fs65.existsSync)((0, import_node_path49.join)(candidate, "skills"))) {
|
|
39071
39188
|
return candidate;
|
|
39072
39189
|
}
|
|
39073
39190
|
}
|
|
@@ -39083,9 +39200,9 @@ async function skillIsCurrent(src, dest) {
|
|
|
39083
39200
|
const list2 = (dir) => {
|
|
39084
39201
|
const out2 = [];
|
|
39085
39202
|
const walk2 = (d, prefix) => {
|
|
39086
|
-
for (const e of (0,
|
|
39203
|
+
for (const e of (0, import_node_fs65.readdirSync)(d, { withFileTypes: true })) {
|
|
39087
39204
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
39088
|
-
if (e.isDirectory()) walk2((0,
|
|
39205
|
+
if (e.isDirectory()) walk2((0, import_node_path49.join)(d, e.name), rel);
|
|
39089
39206
|
else if (e.isFile()) out2.push(rel);
|
|
39090
39207
|
}
|
|
39091
39208
|
};
|
|
@@ -39096,8 +39213,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
39096
39213
|
const shipped = list2(src);
|
|
39097
39214
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
39098
39215
|
for (const rel of shipped) {
|
|
39099
|
-
const a = await (0, import_promises20.readFile)((0,
|
|
39100
|
-
const b = await (0, import_promises20.readFile)((0,
|
|
39216
|
+
const a = await (0, import_promises20.readFile)((0, import_node_path49.join)(src, rel), "utf-8");
|
|
39217
|
+
const b = await (0, import_promises20.readFile)((0, import_node_path49.join)(dest, rel), "utf-8");
|
|
39101
39218
|
if (a !== b) return false;
|
|
39102
39219
|
}
|
|
39103
39220
|
return true;
|
|
@@ -39123,8 +39240,10 @@ var INTENSITY_CHOICES = [
|
|
|
39123
39240
|
{ id: "thorough", label: "thorough", hint: "all tools, all rules (~15s)" }
|
|
39124
39241
|
];
|
|
39125
39242
|
var FORMAL_CHOICES = [
|
|
39126
|
-
{ id: "yes", label: "yes", hint: "a Lean model of the riskiest changed function; blocks only on a REPRODUCED counterexample"
|
|
39127
|
-
|
|
39243
|
+
{ id: "yes", label: "yes", hint: "a Lean model of the riskiest changed function; blocks only on a REPRODUCED counterexample" },
|
|
39244
|
+
// No is the default (review of #255): "yes" downloads ≈800 MB and unpacks
|
|
39245
|
+
// 2.7 GB, and a bare Enter must never do that.
|
|
39246
|
+
{ id: "no", label: "no", hint: "enable later with: verity config formal push", recommended: true }
|
|
39128
39247
|
];
|
|
39129
39248
|
var MOMENT_CHOICES = [
|
|
39130
39249
|
{ id: "stop", label: "On stop", hint: "after every agent turn \u2014 fast feedback while you work", recommended: true },
|
|
@@ -39298,7 +39417,7 @@ async function synthesizeLocally(opts) {
|
|
|
39298
39417
|
async function healStaleAnalysisConfig(globals) {
|
|
39299
39418
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
39300
39419
|
const standardPath = projectPath(STANDARD_FILE);
|
|
39301
|
-
if (!(0,
|
|
39420
|
+
if (!(0, import_node_fs65.existsSync)(configPath) || !(0, import_node_fs65.existsSync)(standardPath)) return;
|
|
39302
39421
|
const validation = validatePatternIds();
|
|
39303
39422
|
if (validation.status !== "invalid") return;
|
|
39304
39423
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
@@ -39395,17 +39514,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
39395
39514
|
async function installSkills(force, step) {
|
|
39396
39515
|
step("Installing skills");
|
|
39397
39516
|
const dataDir = resolveDataDir2();
|
|
39398
|
-
const skillsSource = (0,
|
|
39517
|
+
const skillsSource = (0, import_node_path49.join)(dataDir, "skills");
|
|
39399
39518
|
const skillsDest = ".claude/skills";
|
|
39400
39519
|
let skillsInstalled = 0;
|
|
39401
39520
|
for (const skill of SKILLS) {
|
|
39402
|
-
const src = (0,
|
|
39403
|
-
const dest = (0,
|
|
39404
|
-
if (!(0,
|
|
39521
|
+
const src = (0, import_node_path49.join)(skillsSource, skill);
|
|
39522
|
+
const dest = (0, import_node_path49.join)(skillsDest, skill);
|
|
39523
|
+
if (!(0, import_node_fs65.existsSync)(src)) {
|
|
39405
39524
|
printWarn(` Skill data not found: ${skill}`);
|
|
39406
39525
|
continue;
|
|
39407
39526
|
}
|
|
39408
|
-
if ((0,
|
|
39527
|
+
if ((0, import_node_fs65.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
39409
39528
|
skillsInstalled++;
|
|
39410
39529
|
continue;
|
|
39411
39530
|
}
|
|
@@ -39526,16 +39645,24 @@ async function scaffoldProject(step, defaultsOnly, pluginMode, given = {}) {
|
|
|
39526
39645
|
}
|
|
39527
39646
|
async function offerFormalVerification(defaultsOnly, pluginMode) {
|
|
39528
39647
|
const cfg = readProjectConfig();
|
|
39529
|
-
|
|
39648
|
+
if (cfg.formal_refused) {
|
|
39649
|
+
printWarn(` Formal verification: off \u2014 ${formalRefusalMessage(cfg.formal_refused)}`);
|
|
39650
|
+
return;
|
|
39651
|
+
}
|
|
39530
39652
|
if (cfg.formal === "push") {
|
|
39531
|
-
if (
|
|
39653
|
+
if (findToolchain()) printInfo(" Formal verification at push \u2713");
|
|
39532
39654
|
else printWarn(" Formal verification is on but Lean is missing \u2014 run: verity lean install");
|
|
39533
39655
|
return;
|
|
39534
39656
|
}
|
|
39657
|
+
if (cfg.formal === "off") {
|
|
39658
|
+
printInfo(" Formal verification: off (enable with: verity config formal push)");
|
|
39659
|
+
return;
|
|
39660
|
+
}
|
|
39535
39661
|
if (defaultsOnly || !interactive()) {
|
|
39536
39662
|
printInfo(" Formal verification (a model-based bug finder at push): off \u2014 enable with: verity config formal push");
|
|
39537
39663
|
return;
|
|
39538
39664
|
}
|
|
39665
|
+
const toolchain = findToolchain();
|
|
39539
39666
|
console.log("");
|
|
39540
39667
|
console.log(" Formal verification review \u2014 a model-based bug finder for your riskiest code.");
|
|
39541
39668
|
console.log(" At push, Verity picks the riskiest changed function, checks a small model of");
|
|
@@ -39543,9 +39670,10 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
|
|
|
39543
39670
|
console.log(" Verity for that). Only a reproduced bug can block; most pushes get no model.");
|
|
39544
39671
|
console.log(` Adds /verity-prove <worry> to check any code on demand.${toolchain ? "" : ` Needs to install Lean 4 (${LEAN_DOWNLOAD_SIZE}) on "yes".`}`);
|
|
39545
39672
|
console.log("");
|
|
39546
|
-
const wants = await promptChoice("Formal verification at push?", FORMAL_CHOICES, "
|
|
39673
|
+
const wants = await promptChoice("Formal verification at push?", FORMAL_CHOICES, "no");
|
|
39547
39674
|
if (wants === "yes" && pluginMode) printInfo(" Plugin: the push check works now; /verity:verity-prove arrives with the plugin's next release.");
|
|
39548
39675
|
if (wants !== "yes") {
|
|
39676
|
+
writeProjectConfig({ formal: "off" });
|
|
39549
39677
|
printInfo(" Formal verification: off (enable later with: verity config formal push)");
|
|
39550
39678
|
return;
|
|
39551
39679
|
}
|
|
@@ -39596,7 +39724,7 @@ function registerInitCommand(program2) {
|
|
|
39596
39724
|
const staleMarker = clearStalePluginMarker();
|
|
39597
39725
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
39598
39726
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
39599
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
39727
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs65.existsSync)(m));
|
|
39600
39728
|
if (!isProject) {
|
|
39601
39729
|
printError("No project detected in the current directory.");
|
|
39602
39730
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -39699,7 +39827,7 @@ function registerInitCommand(program2) {
|
|
|
39699
39827
|
untrackMemory: opts.untrackMemory === true,
|
|
39700
39828
|
untrackState: opts.untrackState === true
|
|
39701
39829
|
});
|
|
39702
|
-
const globalVerityDir = (0,
|
|
39830
|
+
const globalVerityDir = (0, import_node_path49.join)(process.env.HOME ?? "", ".verity");
|
|
39703
39831
|
await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
|
|
39704
39832
|
console.log("");
|
|
39705
39833
|
step("Wiring Claude Code hooks");
|
|
@@ -39774,7 +39902,7 @@ function registerInitCommand(program2) {
|
|
|
39774
39902
|
}
|
|
39775
39903
|
step("Your project's Standard");
|
|
39776
39904
|
let haveStandard = false;
|
|
39777
|
-
if ((0,
|
|
39905
|
+
if ((0, import_node_fs65.existsSync)(projectPath(STANDARD_FILE))) {
|
|
39778
39906
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
39779
39907
|
haveStandard = true;
|
|
39780
39908
|
} else {
|
|
@@ -39804,7 +39932,7 @@ function registerInitCommand(program2) {
|
|
|
39804
39932
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
39805
39933
|
init: {
|
|
39806
39934
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39807
|
-
cli_version: true ? "0.34.0-experimental.
|
|
39935
|
+
cli_version: true ? "0.34.0-experimental.37a6dcf" : "dev"
|
|
39808
39936
|
}
|
|
39809
39937
|
});
|
|
39810
39938
|
} catch (err2) {
|
|
@@ -39854,8 +39982,8 @@ function registerInitCommand(program2) {
|
|
|
39854
39982
|
}
|
|
39855
39983
|
|
|
39856
39984
|
// src/commands/uninstall.ts
|
|
39857
|
-
var
|
|
39858
|
-
var
|
|
39985
|
+
var import_node_fs66 = require("node:fs");
|
|
39986
|
+
var import_node_path50 = require("node:path");
|
|
39859
39987
|
function registerUninstallCommand(program2) {
|
|
39860
39988
|
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) => {
|
|
39861
39989
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -39864,11 +39992,11 @@ function registerUninstallCommand(program2) {
|
|
|
39864
39992
|
const actions = [];
|
|
39865
39993
|
const skillsRoot = projectPath(".claude/skills");
|
|
39866
39994
|
for (const name2 of PROJECT_SKILL_NAMES) {
|
|
39867
|
-
const dir = (0,
|
|
39868
|
-
if ((0,
|
|
39995
|
+
const dir = (0, import_node_path50.join)(skillsRoot, name2);
|
|
39996
|
+
if ((0, import_node_fs66.existsSync)(dir)) {
|
|
39869
39997
|
actions.push({
|
|
39870
39998
|
label: `Remove .claude/skills/${name2}/`,
|
|
39871
|
-
apply: () => (0,
|
|
39999
|
+
apply: () => (0, import_node_fs66.rmSync)(dir, { recursive: true, force: true })
|
|
39872
40000
|
});
|
|
39873
40001
|
}
|
|
39874
40002
|
}
|
|
@@ -39882,24 +40010,24 @@ function registerUninstallCommand(program2) {
|
|
|
39882
40010
|
});
|
|
39883
40011
|
}
|
|
39884
40012
|
const verityDir = projectPath(VERITY_DIR);
|
|
39885
|
-
if ((0,
|
|
40013
|
+
if ((0, import_node_fs66.existsSync)(verityDir)) {
|
|
39886
40014
|
actions.push({
|
|
39887
40015
|
label: `Remove ${VERITY_DIR}/`,
|
|
39888
|
-
apply: () => (0,
|
|
40016
|
+
apply: () => (0, import_node_fs66.rmSync)(verityDir, { recursive: true, force: true })
|
|
39889
40017
|
});
|
|
39890
40018
|
}
|
|
39891
40019
|
if (!keepVerityMd) {
|
|
39892
40020
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
39893
|
-
if ((0,
|
|
40021
|
+
if ((0, import_node_fs66.existsSync)(verityMd)) {
|
|
39894
40022
|
actions.push({
|
|
39895
40023
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
39896
|
-
apply: () => (0,
|
|
40024
|
+
apply: () => (0, import_node_fs66.rmSync)(verityMd, { force: true })
|
|
39897
40025
|
});
|
|
39898
40026
|
}
|
|
39899
40027
|
}
|
|
39900
40028
|
const cleanupEmptyDir = (path) => {
|
|
39901
|
-
if ((0,
|
|
39902
|
-
(0,
|
|
40029
|
+
if ((0, import_node_fs66.existsSync)(path) && (0, import_node_fs66.statSync)(path).isDirectory() && (0, import_node_fs66.readdirSync)(path).length === 0) {
|
|
40030
|
+
(0, import_node_fs66.rmdirSync)(path);
|
|
39903
40031
|
}
|
|
39904
40032
|
};
|
|
39905
40033
|
actions.push({
|
|
@@ -39910,11 +40038,11 @@ function registerUninstallCommand(program2) {
|
|
|
39910
40038
|
}
|
|
39911
40039
|
});
|
|
39912
40040
|
const home = process.env.HOME ?? "";
|
|
39913
|
-
const globalVerityDir = (0,
|
|
39914
|
-
if (purgeGlobal && (0,
|
|
40041
|
+
const globalVerityDir = (0, import_node_path50.join)(home, ".verity");
|
|
40042
|
+
if (purgeGlobal && (0, import_node_fs66.existsSync)(globalVerityDir)) {
|
|
39915
40043
|
actions.push({
|
|
39916
40044
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
39917
|
-
apply: () => (0,
|
|
40045
|
+
apply: () => (0, import_node_fs66.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
39918
40046
|
});
|
|
39919
40047
|
}
|
|
39920
40048
|
if (actions.length === 0) {
|
|
@@ -40108,8 +40236,8 @@ function registerTaskCommands(program2) {
|
|
|
40108
40236
|
}
|
|
40109
40237
|
|
|
40110
40238
|
// src/commands/reset.ts
|
|
40111
|
-
var
|
|
40112
|
-
var
|
|
40239
|
+
var import_node_fs67 = require("node:fs");
|
|
40240
|
+
var import_node_path51 = require("node:path");
|
|
40113
40241
|
function registerResetCommand(program2) {
|
|
40114
40242
|
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) => {
|
|
40115
40243
|
const globals = program2.opts();
|
|
@@ -40146,11 +40274,11 @@ function registerResetCommand(program2) {
|
|
|
40146
40274
|
}
|
|
40147
40275
|
const cacheDir = projectPath(CACHE_DIR);
|
|
40148
40276
|
let purged = 0;
|
|
40149
|
-
if ((0,
|
|
40150
|
-
for (const entry of (0,
|
|
40277
|
+
if ((0, import_node_fs67.existsSync)(cacheDir)) {
|
|
40278
|
+
for (const entry of (0, import_node_fs67.readdirSync)(cacheDir)) {
|
|
40151
40279
|
if (entry.startsWith("pending-")) {
|
|
40152
40280
|
try {
|
|
40153
|
-
(0,
|
|
40281
|
+
(0, import_node_fs67.unlinkSync)((0, import_node_path51.join)(cacheDir, entry));
|
|
40154
40282
|
purged++;
|
|
40155
40283
|
} catch {
|
|
40156
40284
|
}
|
|
@@ -40165,19 +40293,19 @@ function registerResetCommand(program2) {
|
|
|
40165
40293
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
40166
40294
|
];
|
|
40167
40295
|
for (const file of filesToClear) {
|
|
40168
|
-
if ((0,
|
|
40296
|
+
if ((0, import_node_fs67.existsSync)(file)) {
|
|
40169
40297
|
try {
|
|
40170
|
-
(0,
|
|
40298
|
+
(0, import_node_fs67.writeFileSync)(file, "");
|
|
40171
40299
|
} catch {
|
|
40172
40300
|
}
|
|
40173
40301
|
}
|
|
40174
40302
|
}
|
|
40175
40303
|
if (opts.all) {
|
|
40176
40304
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
40177
|
-
if ((0,
|
|
40178
|
-
for (const entry of (0,
|
|
40305
|
+
if ((0, import_node_fs67.existsSync)(logsDir)) {
|
|
40306
|
+
for (const entry of (0, import_node_fs67.readdirSync)(logsDir)) {
|
|
40179
40307
|
try {
|
|
40180
|
-
(0,
|
|
40308
|
+
(0, import_node_fs67.unlinkSync)((0, import_node_path51.join)(logsDir, entry));
|
|
40181
40309
|
} catch {
|
|
40182
40310
|
}
|
|
40183
40311
|
}
|
|
@@ -40189,7 +40317,7 @@ function registerResetCommand(program2) {
|
|
|
40189
40317
|
}
|
|
40190
40318
|
|
|
40191
40319
|
// src/commands/reflect.ts
|
|
40192
|
-
var
|
|
40320
|
+
var import_node_fs68 = require("node:fs");
|
|
40193
40321
|
|
|
40194
40322
|
// src/lib/reflection-globs.ts
|
|
40195
40323
|
var MAX_GLOBS = 6;
|
|
@@ -40227,7 +40355,7 @@ async function writeNodeToDisk(args2) {
|
|
|
40227
40355
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
40228
40356
|
);
|
|
40229
40357
|
if (written === 0) return false;
|
|
40230
|
-
return (0,
|
|
40358
|
+
return (0, import_node_fs68.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
|
|
40231
40359
|
} catch {
|
|
40232
40360
|
return false;
|
|
40233
40361
|
}
|
|
@@ -40659,9 +40787,9 @@ function registerRunCommand(program2) {
|
|
|
40659
40787
|
}
|
|
40660
40788
|
|
|
40661
40789
|
// src/commands/telemetry.ts
|
|
40662
|
-
var
|
|
40790
|
+
var import_node_fs69 = require("node:fs");
|
|
40663
40791
|
async function recordTelemetryChoice(choice) {
|
|
40664
|
-
if (!(0,
|
|
40792
|
+
if (!(0, import_node_fs69.existsSync)(projectPath(SETUP_STATE_FILE))) return;
|
|
40665
40793
|
try {
|
|
40666
40794
|
if ((await readSetupState())?.telemetry === choice) return;
|
|
40667
40795
|
await writeSetupState({ telemetry: choice });
|
|
@@ -40738,8 +40866,8 @@ function registerTelemetryCommands(program2) {
|
|
|
40738
40866
|
}
|
|
40739
40867
|
|
|
40740
40868
|
// src/commands/prove.ts
|
|
40741
|
-
var
|
|
40742
|
-
var
|
|
40869
|
+
var import_node_fs70 = require("node:fs");
|
|
40870
|
+
var import_node_path52 = require("node:path");
|
|
40743
40871
|
|
|
40744
40872
|
// src/lib/prove/hint-pool.ts
|
|
40745
40873
|
var STOP2 = /* @__PURE__ */ new Set([
|
|
@@ -40875,7 +41003,7 @@ function registerProveCommand(program2) {
|
|
|
40875
41003
|
process.exit(2);
|
|
40876
41004
|
}
|
|
40877
41005
|
const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
|
|
40878
|
-
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0,
|
|
41006
|
+
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path52.relative)(root, (0, import_node_path52.resolve)(p)) || ".") });
|
|
40879
41007
|
if (opts.hint && paths.length === 0) {
|
|
40880
41008
|
const hit = hintMatches(root, opts.hint);
|
|
40881
41009
|
if (hit.files.length > 0) {
|
|
@@ -40929,7 +41057,7 @@ function registerProveCommand(program2) {
|
|
|
40929
41057
|
});
|
|
40930
41058
|
prove.command("check [model]").description("Elaborate a model (or every model) with the local Lean toolchain and report each property").option("--timeout <ms>", "Per-model timeout in ms", "120000").option("--json", "Machine-readable output").action((model, opts) => {
|
|
40931
41059
|
const root = repoRoot();
|
|
40932
|
-
if (!(0,
|
|
41060
|
+
if (!(0, import_node_fs70.existsSync)((0, import_node_path52.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
40933
41061
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
40934
41062
|
process.exit(2);
|
|
40935
41063
|
}
|
|
@@ -40953,7 +41081,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
40953
41081
|
const reports = [];
|
|
40954
41082
|
for (const f of files) {
|
|
40955
41083
|
const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
|
|
40956
|
-
report.file = (0,
|
|
41084
|
+
report.file = (0, import_node_path52.relative)(root, f);
|
|
40957
41085
|
reports.push(report);
|
|
40958
41086
|
try {
|
|
40959
41087
|
writeResult(root, report);
|
|
@@ -40991,7 +41119,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
40991
41119
|
printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
|
|
40992
41120
|
process.exit(2);
|
|
40993
41121
|
}
|
|
40994
|
-
if (!(0,
|
|
41122
|
+
if (!(0, import_node_fs70.existsSync)((0, import_node_path52.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
40995
41123
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
40996
41124
|
process.exit(2);
|
|
40997
41125
|
}
|
|
@@ -41022,7 +41150,7 @@ ${report.error ?? ""}`);
|
|
|
41022
41150
|
printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
|
|
41023
41151
|
return;
|
|
41024
41152
|
}
|
|
41025
|
-
const modelSource = readRegularFileInRoot(root, (0,
|
|
41153
|
+
const modelSource = readRegularFileInRoot(root, (0, import_node_path52.relative)(root, file), 512 * 1024);
|
|
41026
41154
|
if (!opts.json) printInfo(`replaying ${targets.length} counterexample(s) of ${model} in network-less containers (${Math.min(targets.length, REPLAY_CONCURRENCY)} at a time)\u2026`);
|
|
41027
41155
|
const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
|
|
41028
41156
|
const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
|
|
@@ -41042,7 +41170,7 @@ ${report.error ?? ""}`);
|
|
|
41042
41170
|
});
|
|
41043
41171
|
prove.command("auto [files...]").description("The formal phase the pre-push guard runs: select one risky symbol among changed files, generate a model, check it, replay counterexamples (default files: the commits ahead of upstream)").option("--deadline <ms>", "Budget for the whole phase", "170000").option("--json", "Machine-readable output").action(async (paths, opts) => {
|
|
41044
41172
|
const root = repoRoot();
|
|
41045
|
-
let files = paths.map((p) => (0,
|
|
41173
|
+
let files = paths.map((p) => (0, import_node_path52.relative)(root, (0, import_node_path52.resolve)(p)));
|
|
41046
41174
|
if (files.length === 0) {
|
|
41047
41175
|
const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
|
|
41048
41176
|
const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
|
|
@@ -41102,7 +41230,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41102
41230
|
let revise;
|
|
41103
41231
|
if (opts.revise) {
|
|
41104
41232
|
const existing = resolveModelFile(root, opts.revise);
|
|
41105
|
-
const src = existing ? readRegularFileInRoot(root, (0,
|
|
41233
|
+
const src = existing ? readRegularFileInRoot(root, (0, import_node_path52.relative)(root, existing), 64 * 1024) : null;
|
|
41106
41234
|
if (!src || !src.ok || !opts.note) {
|
|
41107
41235
|
printError('--revise needs an existing model under Models/ and --note "<what the replay showed>"');
|
|
41108
41236
|
process.exit(2);
|
|
@@ -41141,8 +41269,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41141
41269
|
});
|
|
41142
41270
|
prove.command("waive <file>").description("Dismiss the remembered formal finding(s) on a file for its current bytes \u2014 the accepted-risk path for a formal block").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action((file, opts) => {
|
|
41143
41271
|
const root = repoRoot();
|
|
41144
|
-
const rel0 = (0,
|
|
41145
|
-
const rel = rel0.startsWith("..") || (0,
|
|
41272
|
+
const rel0 = (0, import_node_path52.relative)(root, (0, import_node_path52.isAbsolute)(file) ? file : (0, import_node_path52.join)(root, file)).replace(/\\/g, "/");
|
|
41273
|
+
const rel = rel0.startsWith("..") || (0, import_node_path52.isAbsolute)(rel0) ? null : rel0;
|
|
41146
41274
|
if (!rel) {
|
|
41147
41275
|
printError(`${file} is not inside this repository`);
|
|
41148
41276
|
process.exit(2);
|
|
@@ -41158,8 +41286,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41158
41286
|
});
|
|
41159
41287
|
prove.command("hash <file>").description("Print the sha256 of a file, for a model header (Verity.model \u2026 sha256). Path is REPO-relative, as in the header").action((file) => {
|
|
41160
41288
|
const root = repoRoot();
|
|
41161
|
-
const rel = (0,
|
|
41162
|
-
const digest = rel.startsWith("..") || (0,
|
|
41289
|
+
const rel = (0, import_node_path52.relative)(root, (0, import_node_path52.isAbsolute)(file) ? file : (0, import_node_path52.join)(root, file));
|
|
41290
|
+
const digest = rel.startsWith("..") || (0, import_node_path52.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
|
|
41163
41291
|
if (!digest) {
|
|
41164
41292
|
printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
|
|
41165
41293
|
process.exit(2);
|
|
@@ -41193,10 +41321,10 @@ function refreshScaffold(root) {
|
|
|
41193
41321
|
}
|
|
41194
41322
|
|
|
41195
41323
|
// src/commands/lean.ts
|
|
41196
|
-
var
|
|
41324
|
+
var import_node_fs71 = require("node:fs");
|
|
41197
41325
|
var import_node_child_process20 = require("node:child_process");
|
|
41198
41326
|
var import_node_os11 = require("node:os");
|
|
41199
|
-
var
|
|
41327
|
+
var import_node_path53 = require("node:path");
|
|
41200
41328
|
function registerLeanCommand(program2) {
|
|
41201
41329
|
const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
|
|
41202
41330
|
lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
|
|
@@ -41213,7 +41341,7 @@ function registerLeanCommand(program2) {
|
|
|
41213
41341
|
const managed = pinnedVersionDir();
|
|
41214
41342
|
const matches = version ? version.includes(pin) : false;
|
|
41215
41343
|
if (opts.json) {
|
|
41216
|
-
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0,
|
|
41344
|
+
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs71.existsSync)((0, import_node_path53.join)(managed, "bin")), asset: leanAssetName() });
|
|
41217
41345
|
return;
|
|
41218
41346
|
}
|
|
41219
41347
|
printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
|
|
@@ -41231,7 +41359,7 @@ function registerLeanCommand(program2) {
|
|
|
41231
41359
|
process.exit(2);
|
|
41232
41360
|
}
|
|
41233
41361
|
const dir = pinnedVersionDir();
|
|
41234
|
-
if ((0,
|
|
41362
|
+
if ((0, import_node_fs71.existsSync)((0, import_node_path53.join)(dir, "bin", "lake")) && !opts.force) {
|
|
41235
41363
|
printInfo(`already installed at ${dir}`);
|
|
41236
41364
|
return;
|
|
41237
41365
|
}
|
|
@@ -41267,18 +41395,18 @@ function registerLeanCommand(program2) {
|
|
|
41267
41395
|
});
|
|
41268
41396
|
lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
|
|
41269
41397
|
const dir = pinnedVersionDir();
|
|
41270
|
-
if (!(0,
|
|
41398
|
+
if (!(0, import_node_fs71.existsSync)(dir)) {
|
|
41271
41399
|
printInfo("nothing to remove");
|
|
41272
41400
|
return;
|
|
41273
41401
|
}
|
|
41274
|
-
(0,
|
|
41402
|
+
(0, import_node_fs71.rmSync)(dir, { recursive: true, force: true });
|
|
41275
41403
|
printInfo(`removed ${dir}`);
|
|
41276
41404
|
});
|
|
41277
41405
|
}
|
|
41278
41406
|
|
|
41279
41407
|
// src/cli.ts
|
|
41280
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.
|
|
41281
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.0-experimental.
|
|
41408
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.37a6dcf").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) => {
|
|
41409
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.0-experimental.37a6dcf");
|
|
41282
41410
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
41283
41411
|
try {
|
|
41284
41412
|
await foldLegacyLocalCredential();
|